зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1534937 - Update webgl-conf checkout to tip. r=lsalzman
Differential Revision: https://phabricator.services.mozilla.com/D28592 --HG-- rename : dom/canvas/test/webgl-conf/checkout/conformance/rendering/out-of-bounds-index-buffers.html => dom/canvas/test/webgl-conf/checkout/conformance/rendering/out-of-bounds-array-buffers.html rename : dom/canvas/test/webgl-conf/checkout/conformance/attribs/gl-bindAttribLocation-aliasing.html => dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ext-float-blend.html rename : dom/canvas/test/webgl-conf/checkout/conformance2/extensions/webgl_multiview.html => dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2.html rename : dom/canvas/test/webgl-conf/checkout/conformance2/extensions/webgl_multiview_depth.html => dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_depth.html rename : dom/canvas/test/webgl-conf/checkout/conformance2/extensions/webgl_multiview_draw_buffers.html => dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_draw_buffers.html rename : dom/canvas/test/webgl-conf/checkout/conformance2/extensions/webgl_multiview_flat_varying.html => dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_flat_varying.html rename : dom/canvas/test/webgl-conf/checkout/conformance2/extensions/webgl_multiview_instanced_draw.html => dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_instanced_draw.html rename : dom/canvas/test/webgl-conf/checkout/conformance2/extensions/webgl_multiview_non_multiview_shaders.html => dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_non_multiview_shaders.html rename : dom/canvas/test/webgl-conf/checkout/conformance2/extensions/webgl_multiview_single_view_operations.html => dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_single_view_operations.html rename : dom/canvas/test/webgl-conf/checkout/conformance2/extensions/webgl_multiview_timer_query.html => dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_timer_query.html rename : dom/canvas/test/webgl-conf/checkout/conformance2/extensions/webgl_multiview_transform_feedback.html => dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2_transform_feedback.html rename : dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/tex-unpack-params-imagedata.html => dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/generate-mipmap-with-large-base-level.html rename : dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions.html => dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_00.html rename : dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/geometric.html => dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_01.html rename : dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/float_compare.html => dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_02.html rename : dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/int_compare.html => dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_03.html rename : dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/bool_compare.html => dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_04.html rename : dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/selection.html => dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_05.html rename : dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/sequence.html => dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/shaderoperator/common_functions_06.html rename : dom/canvas/test/webgl-conf/checkout/js/tests/webgl_multiview_util.js => dom/canvas/test/webgl-conf/checkout/js/tests/ovr_multiview2_util.js extra : moz-landing-system : lando
This commit is contained in:
Родитель
3415e4de5f
Коммит
88d6589226
|
@ -23,8 +23,7 @@ a formal conformance submission.
|
|||
|
||||
4. Verify that the User Agent and WebGL renderer strings identify your browser and target correctly.
|
||||
|
||||
5. Copy the contents of the text summary (starting with "WebGL Conformance Test Results") and send via email to
|
||||
webgl_conformance_submissions@khronos.org
|
||||
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.
|
||||
|
@ -77,4 +76,4 @@ The dates below are when work on the conformance suite version was started.
|
|||
- 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
|
||||
- 2016/11/21: Version 2.0.1
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
--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
|
||||
|
@ -11,3 +12,4 @@ 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
|
||||
|
|
|
@ -1,26 +1,7 @@
|
|||
<!--
|
||||
/*
|
||||
** Copyright (c) 2014 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
Copyright (c) 2019 The Khronos Group Inc.
|
||||
Use of this source code is governed by an MIT-style license that can be
|
||||
found in the LICENSE.txt file.
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
<!--
|
||||
|
||||
/*
|
||||
** Copyright (c) 2018 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
-->
|
||||
|
||||
<!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>
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
<!--
|
||||
/*
|
||||
** Copyright (c) 2019 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
-->
|
||||
|
||||
<!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>
|
||||
|
|
@ -51,7 +51,9 @@
|
|||
</script>
|
||||
|
||||
<script id="fshader" type="x-shader/x-fragment">
|
||||
void main() { }
|
||||
void main() {
|
||||
gl_FragColor = vec4(1);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
|
|
|
@ -10,4 +10,5 @@ index-validation-crash-with-buffer-sub-data.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
|
||||
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
<!--
|
||||
|
||||
/*
|
||||
** Copyright (c) 2018 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
-->
|
||||
|
||||
<!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>
|
||||
|
|
@ -0,0 +1,258 @@
|
|||
<!--
|
||||
|
||||
/*
|
||||
** Copyright (c) 2019 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
-->
|
||||
|
||||
<!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>
|
|
@ -37,6 +37,6 @@ webgl-debug-shaders.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.3 --max-version 1.9.9 webgl-draw-buffers-feedback-loop.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
|
||||
|
|
|
@ -33,21 +33,31 @@
|
|||
<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";
|
||||
function testPrologue(gl, extensionTypeName) {
|
||||
if (!gl.getExtension(extensionTypeName)) {
|
||||
testPassed("No " + extensionTypeName + " support -- this is legal");
|
||||
return false;
|
||||
|
||||
description("Test OES_texture_float_linear, if available.");
|
||||
|
||||
const wtu = WebGLTestUtils;
|
||||
const gl = wtu.create3DContext();
|
||||
|
||||
(function() {
|
||||
if (!(gl instanceof WebGL2RenderingContext)) {
|
||||
if (!gl.getExtension("OES_texture_float")) {
|
||||
testPassed("No OES_texture_float support -- this is legal");
|
||||
return;
|
||||
}
|
||||
}
|
||||
testPassed("Successfully enabled " + extensionTypeName + " extension");
|
||||
return true;
|
||||
}
|
||||
testTexLinear(gl, "OES_texture_float_linear", "RGBA32F", "FLOAT");
|
||||
})();
|
||||
|
||||
debug("");
|
||||
const successfullyParsed = true;
|
||||
</script>
|
||||
</head>
|
||||
<body onload='generateTest("OES_texture_float", "OES_texture_float_linear", "FLOAT", testPrologue)()'>
|
||||
<div id="description"></div>
|
||||
<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
|
||||
<div id="console"></div>
|
||||
<script src="../../js/js-test-post.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -51,7 +51,7 @@ function testPrologue(gl) {
|
|||
<canvas id="example" width="32" height="32"></canvas>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<video width="640" height="228" id="vid" controls>
|
||||
<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"' />
|
||||
|
|
|
@ -29,10 +29,11 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>WebGL OES_texture_float Conformance Tests</title>
|
||||
<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>
|
||||
|
@ -73,7 +74,7 @@ void main()
|
|||
</script>
|
||||
<script>
|
||||
"use strict";
|
||||
description("This test verifies the functionality of the OES_texture_float extension, if it is available.");
|
||||
description("This test verifies the functionality of the OES_texture_float and WEBGL_color_buffer_float extensions, if available.");
|
||||
|
||||
debug("");
|
||||
|
||||
|
@ -127,6 +128,19 @@ if (!gl) {
|
|||
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);
|
||||
}
|
||||
})();
|
||||
|
||||
|
@ -315,6 +329,114 @@ function runUniqueObjectTest()
|
|||
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;
|
||||
|
|
|
@ -33,24 +33,35 @@
|
|||
<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";
|
||||
function testPrologue(gl, extensionTypeName) {
|
||||
var ext = null;
|
||||
if (!(ext = gl.getExtension(extensionTypeName))) {
|
||||
testPassed("No " + extensionTypeName + " support -- this is legal");
|
||||
return false;
|
||||
|
||||
description("Test OES_texture_half_float_linear, if available.");
|
||||
|
||||
const wtu = WebGLTestUtils;
|
||||
const gl = wtu.create3DContext();
|
||||
|
||||
(function() {
|
||||
if (gl instanceof WebGL2RenderingContext)
|
||||
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;
|
||||
testPassed("Successfully enabled " + extensionTypeName + " extension");
|
||||
return true;
|
||||
}
|
||||
testTexLinear(gl, "OES_texture_half_float_linear", undefined, "HALF_FLOAT_OES");
|
||||
})();
|
||||
|
||||
debug("");
|
||||
const successfullyParsed = true;
|
||||
</script>
|
||||
</head>
|
||||
<body onload='generateTest("OES_texture_half_float", "OES_texture_half_float_linear", "HALF_FLOAT_OES", testPrologue)()'>
|
||||
<div id="description"></div>
|
||||
<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
|
||||
<div id="console"></div>
|
||||
<script src="../../js/js-test-post.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -56,7 +56,7 @@ function testPrologue(gl) {
|
|||
<canvas id="example" width="32" height="32"></canvas>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<video width="640" height="228" id="vid" controls>
|
||||
<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"' />
|
||||
|
|
|
@ -224,33 +224,6 @@ function getNumberOfChannels(format)
|
|||
return 2;
|
||||
}
|
||||
|
||||
function getFormatName(format)
|
||||
{
|
||||
if (format == gl.RGBA)
|
||||
return "RGBA";
|
||||
else if (format == gl.RGB)
|
||||
return "RGB";
|
||||
else if (format == gl.LUMINANCE)
|
||||
return "LUMINANCE";
|
||||
else if (format == gl.ALPHA)
|
||||
return "ALPHA";
|
||||
else if (format == gl.LUMINANCE_ALPHA)
|
||||
return "LUMINANCE_ALPHA";
|
||||
}
|
||||
|
||||
function getTypeName(type) {
|
||||
if (type === gl.UNSIGNED_BYTE)
|
||||
return "UNSIGNED_BYTE";
|
||||
else if (type === ext.HALF_FLOAT_OES)
|
||||
return "HALF_FLOAT_OES";
|
||||
else if (type === gl.UNSIGNED_SHORT_4_4_4_4)
|
||||
return "UNSIGNED_SHORT_4_4_4_4";
|
||||
else if (type === gl.UNSIGNED_SHORT_5_5_5_1)
|
||||
return "UNSIGNED_SHORT_5_6_5";
|
||||
else if (type === gl.FLOAT)
|
||||
return "FLOAT";
|
||||
}
|
||||
|
||||
function allocateTexture()
|
||||
{
|
||||
var texture = gl.createTexture();
|
||||
|
@ -272,7 +245,7 @@ function runTextureCreationTest(extensionEnabled, opt_format, opt_data, opt_expe
|
|||
if (!extensionEnabled || !opt_expected)
|
||||
expectSuccess = false;
|
||||
debug("Testing texture creation with extension " + (extensionEnabled ? "enabled" : "disabled") +
|
||||
", format " + getFormatName(format) + ", and data " + (data ? "non-null" : "null") +
|
||||
", format " + wtu.glEnumToString(gl, format) + ", and data " + (data ? "non-null" : "null") +
|
||||
". Expect " + (expectSuccess ? "Success" : "Failure"));
|
||||
|
||||
var texture = allocateTexture();
|
||||
|
@ -386,9 +359,9 @@ function runUniqueObjectTest()
|
|||
// 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 = getTypeName(glType);
|
||||
var typeName = wtu.glEnumToString(gl, glType);
|
||||
|
||||
debug(getFormatName(glFormat) + " framebuffer with " + typeName + " readback.");
|
||||
debug(wtu.glEnumToString(gl, glFormat) + " framebuffer with " + typeName + " readback.");
|
||||
|
||||
var arrayBuffer = new arrayBufferConstructor(4);
|
||||
gl.readPixels(0, 0, 1, 1, gl.RGBA, glType, arrayBuffer);
|
||||
|
@ -437,7 +410,7 @@ function runFramebufferTest() {
|
|||
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(getFormatName(badFormat) + " framebuffer");
|
||||
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");
|
||||
|
@ -461,7 +434,7 @@ function runFramebufferTest() {
|
|||
arrayBufferHalfFloatInput[3] = 0x3A00; // 0.75 in half float
|
||||
|
||||
[gl.RGBA, gl.RGB].forEach(function(goodFormat) {
|
||||
debug(getFormatName(goodFormat) + " framebuffer tests");
|
||||
debug(wtu.glEnumToString(gl, goodFormat) + " framebuffer tests");
|
||||
debug("");
|
||||
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, goodFormat, 1, 1, 0, goodFormat, ext.HALF_FLOAT_OES, arrayBufferHalfFloatInput);
|
||||
|
@ -479,7 +452,7 @@ function runFramebufferTest() {
|
|||
|
||||
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: " + getFormatName(implementationColorReadFormat));
|
||||
"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);
|
||||
|
||||
|
@ -494,7 +467,7 @@ function runFramebufferTest() {
|
|||
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: " + getTypeName(implementationColorReadType));
|
||||
"Received: " + wtu.glEnumToString(gl, implementationColorReadType));
|
||||
|
||||
// Test the RGBA/HALF_FLOAT_OES combination
|
||||
if (implementationColorReadFormat === gl.RGBA && implementationColorReadType === ext.HALF_FLOAT_OES) {
|
||||
|
|
|
@ -1785,8 +1785,8 @@ function testASTCTexture(test, useTexStorage) {
|
|||
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 = [0, 0, 0, 0];
|
||||
wtu.checkCanvas(gl, clearColor, "texture should be initialized to black");
|
||||
var clearColor = [255, 0, 255, 255];
|
||||
wtu.checkCanvas(gl, clearColor, "texture should be initialized to error color");
|
||||
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 {
|
||||
|
|
|
@ -157,6 +157,11 @@ function runTestExtension() {
|
|||
testDXT1_RGBA();
|
||||
testDXT3_RGBA();
|
||||
testDXT5_RGBA();
|
||||
|
||||
// Test compressed PBOs with a single format
|
||||
if (contextVersion >= 2) {
|
||||
testDXT5_RGBA_PBO();
|
||||
}
|
||||
}
|
||||
|
||||
function testDXT1_RGB() {
|
||||
|
@ -609,6 +614,46 @@ function testDXTTexture(test, useTexStorage) {
|
|||
}
|
||||
}
|
||||
|
||||
function testDXT5_RGBA_PBO() {
|
||||
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");
|
||||
|
||||
// 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");
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
|
@ -48,7 +48,7 @@ uniform sampler2D u_texture;
|
|||
uniform vec2 u_resolution;
|
||||
void main()
|
||||
{
|
||||
vec2 texcoord = gl_FragCoord.xy / u_resolution;
|
||||
vec2 texcoord = (gl_FragCoord.xy - vec2(0.5)) / (u_resolution - vec2(1.0));
|
||||
gl_FragColor = texture2D(u_texture, texcoord);
|
||||
}
|
||||
</script>
|
||||
|
@ -142,7 +142,8 @@ function dumpIt(gl, res, msg) {
|
|||
function runTestExtension(unpackFlipY) {
|
||||
debug("Testing WEBGL_depth_texture. UNPACK_FLIP_Y_WEBGL: " + unpackFlipY);
|
||||
|
||||
var res = 8;
|
||||
const res = 2;
|
||||
const destRes = 4;
|
||||
|
||||
// make canvas for testing.
|
||||
canvas2 = document.createElement("canvas");
|
||||
|
@ -154,7 +155,7 @@ function runTestExtension(unpackFlipY) {
|
|||
|
||||
var program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['a_position']);
|
||||
gl.useProgram(program);
|
||||
gl.uniform2f(gl.getUniformLocation(program, "u_resolution"), res, res);
|
||||
gl.uniform2f(gl.getUniformLocation(program, "u_resolution"), destRes, destRes);
|
||||
|
||||
var buffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
||||
|
@ -213,6 +214,7 @@ function runTestExtension(unpackFlipY) {
|
|||
];
|
||||
|
||||
for (var jj = 0; jj < filterModes.length; ++jj) {
|
||||
debug('');
|
||||
debug('testing ' + filterModes[jj] + ' filtering');
|
||||
var filterMode = gl[filterModes[jj]];
|
||||
|
||||
|
@ -280,60 +282,101 @@ function runTestExtension(unpackFlipY) {
|
|||
// use the default texture to render with while we return to the depth texture.
|
||||
gl.bindTexture(gl.TEXTURE_2D, null);
|
||||
|
||||
// render the z-quad
|
||||
gl.enable(gl.DEPTH_TEST);
|
||||
gl.clearColor(1, 0, 0, 1);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||||
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
||||
/* 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;
|
||||
|
||||
dumpIt(gl, res, "--first--");
|
||||
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.clearColor(0, 0, 1, 1);
|
||||
|
||||
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);
|
||||
|
||||
var actualPixels = new Uint8Array(res * res * 4);
|
||||
gl.readPixels(0, 0, res, res, gl.RGBA, gl.UNSIGNED_BYTE, actualPixels);
|
||||
|
||||
dumpIt(gl, res, "--depth--");
|
||||
|
||||
// Check that each pixel's R value is less than that of the previous pixel
|
||||
// in either direction. Basically verify we have a gradient.
|
||||
var success = true;
|
||||
for (var yy = 0; yy < res; ++yy) {
|
||||
for (var xx = 0; xx < res; ++xx) {
|
||||
var actual = (yy * res + xx) * 4;
|
||||
var left = actual - 4;
|
||||
var down = actual - res * 4;
|
||||
var actualPixels = new Uint8Array(destRes * destRes * 4);
|
||||
gl.readPixels(0, 0, destRes, destRes, gl.RGBA, gl.UNSIGNED_BYTE, actualPixels);
|
||||
|
||||
if (xx > 0) {
|
||||
if (actualPixels[actual] <= actualPixels[left]) {
|
||||
testFailed("actual(" + actualPixels[actual] + ") < left(" + actualPixels[left] + ")");
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
if (yy > 0) {
|
||||
if (actualPixels[actual] <= actualPixels[down]) {
|
||||
testFailed("actual(" + actualPixels[actual] + ") < down(" + actualPixels[down] + ")");
|
||||
success = false;
|
||||
}
|
||||
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 that bottom left corner is vastly different thatn top right.
|
||||
if (actualPixels[(res * res - 1) * 4] - actualPixels[0] < 0xC0) {
|
||||
testFailed("corners are not different enough");
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (success) {
|
||||
testPassed("depth texture rendered correctly.");
|
||||
}
|
||||
|
||||
// check limitations
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
|
||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl[typeInfo.attachment], gl.TEXTURE_2D, null, 0);
|
||||
|
|
|
@ -1,161 +0,0 @@
|
|||
<!--
|
||||
|
||||
/*
|
||||
** Copyright (c) 2016 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>WebGL Rendering and Sampling Feedback Loop Tests For WEBGL_draw_buffers Extension</title>
|
||||
<link rel="stylesheet" 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">
|
||||
attribute vec4 aPosition;
|
||||
attribute vec2 aTexCoord;
|
||||
varying vec2 texCoord;
|
||||
void main() {
|
||||
gl_Position = aPosition;
|
||||
texCoord = aTexCoord;
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="fshader" 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>
|
||||
"use strict";
|
||||
|
||||
var wtu = WebGLTestUtils;
|
||||
var canvas = document.getElementById("example");
|
||||
description("This test verifies the functionality of rendering to the same texture where it samples from.");
|
||||
|
||||
var gl = wtu.create3DContext(canvas);
|
||||
|
||||
var width = 8;
|
||||
var height = 8;
|
||||
var tex0;
|
||||
var tex1;
|
||||
var fbo;
|
||||
var ext;
|
||||
var program;
|
||||
var positionLoc;
|
||||
var texCoordLoc;
|
||||
|
||||
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");
|
||||
|
||||
init();
|
||||
|
||||
// The sampling texture is bound to COLOR_ATTACHMENT1 during resource allocation
|
||||
allocate_resource();
|
||||
|
||||
rendering_sampling_feedback_loop([gl.NONE, ext.COLOR_ATTACHMENT1_WEBGL], gl.INVALID_OPERATION);
|
||||
rendering_sampling_feedback_loop([gl.COLOR_ATTACHMENT0, ext.COLOR_ATTACHMENT1_WEBGL], gl.INVALID_OPERATION);
|
||||
rendering_sampling_feedback_loop([gl.COLOR_ATTACHMENT0, gl.NONE], gl.NO_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
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);
|
||||
}
|
||||
|
||||
function allocate_resource() {
|
||||
tex0 = gl.createTexture();
|
||||
tex1 = gl.createTexture();
|
||||
fbo = gl.createFramebuffer();
|
||||
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, gl.UNSIGNED_BYTE, gl.RGBA);
|
||||
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex1);
|
||||
var texLoc = gl.getUniformLocation(program, "tex");
|
||||
gl.uniform1i(texLoc, 0);
|
||||
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
|
||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex0, 0);
|
||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, ext.COLOR_ATTACHMENT1_WEBGL, gl.TEXTURE_2D, tex1, 0);
|
||||
}
|
||||
|
||||
function rendering_sampling_feedback_loop(draw_buffers, error) {
|
||||
// gl.drawBuffers(draw_buffers);
|
||||
ext.drawBuffersWEBGL(draw_buffers);
|
||||
|
||||
// Make sure framebuffer is complete before feedback loop detection
|
||||
if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
|
||||
testFailed("Framebuffer incomplete.");
|
||||
return;
|
||||
}
|
||||
|
||||
wtu.clearAndDrawUnitQuad(gl);
|
||||
wtu.glErrorShouldBe(gl, error, "Rendering to a texture where it samples from should geneates INVALID_OPERATION. Otherwise, it should be NO_ERROR");
|
||||
}
|
||||
|
||||
gl.bindTexture(gl.TEXTURE_2D, null);
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
gl.deleteTexture(tex0);
|
||||
gl.deleteTexture(tex1);
|
||||
gl.deleteFramebuffer(fbo);
|
||||
|
||||
var successfullyParsed = true;
|
||||
</script>
|
||||
<script src="../../js/js-test-post.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -531,7 +531,7 @@ function runDrawTests() {
|
|||
} 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);
|
||||
}
|
||||
|
@ -546,13 +546,11 @@ function runDrawTests() {
|
|||
|
||||
debug("test that gl_FragColor does not broadcast unless extension is enabled in fragment shader");
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
|
||||
ext.drawBuffersWEBGL([gl.COLOR_ATTACHMENT0]); // While the WG debates whether how to handle this.
|
||||
ext.drawBuffersWEBGL(bufs);
|
||||
gl.useProgram(redProgram);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
|
||||
wtu.drawUnitQuad(gl);
|
||||
|
||||
drawBuffersUtils.checkAttachmentsForColorFn(attachments, function(attachment, index) {
|
||||
return (index == 0) ? [255, 0, 0, 255] : [0, 255, 0, 255];
|
||||
});
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Active draw buffers with missing frag outputs.");
|
||||
|
||||
debug("test that gl_FragColor broadcasts if extension is enabled in fragment shader");
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
|
|
@ -0,0 +1,834 @@
|
|||
<!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>
|
||||
</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');
|
||||
|
||||
// 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_multi_draw', false);
|
||||
doTest('WEBGL_multi_draw_instanced', true);
|
||||
}
|
||||
|
||||
function doTest(extensionName, instanced) {
|
||||
const ext = gl.getExtension(extensionName);
|
||||
|
||||
if (!runSupportedTest(extensionName, ext)) {
|
||||
return;
|
||||
}
|
||||
|
||||
function runValidationTests() {
|
||||
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 ]), 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, 0]), gl.STATIC_DRAW);
|
||||
|
||||
const instanceBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, instanceBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0, 1, 2, 3 ]), gl.STATIC_DRAW);
|
||||
|
||||
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() {
|
||||
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 ]), gl.STATIC_DRAW);
|
||||
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() {
|
||||
// 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, gl.STATIC_DRAW);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
|
||||
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
|
||||
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, instanceBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1, 2, 3, 4]), gl.STATIC_DRAW);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
const firsts = new Uint32Array(tri_count);
|
||||
const counts = new Uint32Array(tri_count);
|
||||
const offsets = new Uint32Array(tri_count);
|
||||
const instances = new Uint32Array(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 = new Uint32Array(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' : ''
|
||||
));
|
||||
|
||||
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,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
runValidationTests();
|
||||
runShaderTests();
|
||||
runPixelTests();
|
||||
}
|
||||
|
||||
runTest();
|
||||
|
||||
const successfullyParsed = true;
|
||||
</script>
|
||||
<script src="../../js/js-test-post.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -39,7 +39,7 @@
|
|||
<canvas id="example" width="256" height="256" style="width: 16px; height: 16px;"></canvas>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<script id="vshader2d0" type="x-shader/x-vertex">
|
||||
<script id="vshader2dvec3" type="x-shader/x-vertex">
|
||||
attribute vec4 vPosition;
|
||||
varying vec4 color;
|
||||
uniform sampler2D tex;
|
||||
|
@ -50,7 +50,7 @@ void main() {
|
|||
color = texture2DProjLod(tex, vec3(0.75 * divisor, 0.25 * divisor, divisor), lod);
|
||||
}
|
||||
</script>
|
||||
<script id="vshader2d1" type="x-shader/x-vertex">
|
||||
<script id="vshader2dvec4" type="x-shader/x-vertex">
|
||||
attribute vec4 vPosition;
|
||||
varying vec4 color;
|
||||
uniform sampler2D tex;
|
||||
|
@ -89,6 +89,8 @@ var colors = [
|
|||
{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) {
|
||||
|
@ -97,58 +99,78 @@ if (gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS) > 0) {
|
|||
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");
|
||||
for (var ss = 0; ss < 2; ++ss) {
|
||||
debug("");
|
||||
debug(ss ? "testing vec4 version" : "testing vec3 version");
|
||||
var program = wtu.setupProgram(
|
||||
gl, ['vshader2d' + ss, 'fshader2d'], ['vPosition', 'texCoord0'], [0, 1]);
|
||||
wtu.setupUnitQuad(gl, 0, 1);
|
||||
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);
|
||||
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);
|
||||
|
||||
var c = document.createElement("canvas");
|
||||
c.width = size;
|
||||
c.height = size;
|
||||
var ctx = c.getContext("2d");
|
||||
ctx.fillStyle = "rgb(0,0,0)";
|
||||
ctx.fillRect(0, 0, size, size);
|
||||
ctx.fillStyle = "rgb(" + color.color[0] + "," + color.color[1] + "," + color.color[2] + ")";
|
||||
ctx.fillRect(size / 2, 0, size / 2, size / 2);
|
||||
|
||||
gl.texImage2D(gl.TEXTURE_2D, ii, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, c);
|
||||
}
|
||||
|
||||
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];
|
||||
// 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);
|
||||
wtu.clearAndDrawUnitQuad(gl);
|
||||
wtu.checkCanvas(
|
||||
gl, lodColor.color,
|
||||
"sampling with lod = " + ii +
|
||||
" divider = " + div +
|
||||
" should be " + lodColor.name);
|
||||
|
||||
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.");
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@ functions/copyTexSubImage2D.html
|
|||
functions/copyTexSubImage2DBadArgs.html
|
||||
functions/deleteBufferBadArgs.html
|
||||
functions/drawArrays.html
|
||||
functions/drawArraysOutOfBounds.html
|
||||
functions/drawElements.html
|
||||
functions/isTests.html
|
||||
--min-version 1.0.2 functions/isTestsBadArgs.html
|
||||
|
@ -51,7 +50,5 @@ functions/vertexAttribBadArgs.html
|
|||
functions/vertexAttribPointer.html
|
||||
functions/vertexAttribPointerBadArgs.html
|
||||
glsl/arrayOutOfBounds.html
|
||||
#glsl/longLoops.html // No interactive tests.
|
||||
glsl/uniformOutOfBounds.html
|
||||
#glsl/unusedAttribsUniforms.html // No interactive tests.
|
||||
|
||||
|
|
|
@ -359,6 +359,7 @@ randomImage = function(w,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');
|
||||
|
|
|
@ -1,607 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<!--
|
||||
|
||||
/*
|
||||
** Copyright (c) 2012 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
-->
|
||||
|
||||
<title>OpenGL for the web</title>
|
||||
|
||||
<script type="application/javascript" src="../util.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
|
||||
function log(msg) {
|
||||
document.getElementById('note').textContent += "\n"+msg;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function init(ev) {
|
||||
var canvas = document.getElementById('canvas');
|
||||
var gl = getGLContext(canvas);
|
||||
|
||||
var shader = new Shader(gl, "ppix-vert", "ppix-frag");
|
||||
shader.compile();
|
||||
var fbo = new FBO(gl, canvas.width, canvas.height);
|
||||
var fbo2 = new FBO(gl, canvas.width, canvas.height);
|
||||
var fbo3 = new FBO(gl, canvas.width, canvas.height);
|
||||
var depth = new Shader(gl, "depth-vert", "depth-frag");
|
||||
var identity = new Filter(gl, "identity-vert", "identity-frag");
|
||||
var unpremult = new Filter(gl, "identity-vert", "unpremult-frag");
|
||||
var hblur = new Filter(gl, "identity-vert", "hblur-frag");
|
||||
var vblur = new Filter(gl, "identity-vert", "vblur-frag");
|
||||
var hdof = new Filter(gl, "identity-vert", "hdof-frag");
|
||||
var vdof = new Filter(gl, "identity-vert", "vdof-frag");
|
||||
|
||||
redraw(canvas, gl, shader, fbo, fbo2, fbo3, depth, identity, unpremult, hblur, vblur, hdof, vdof);
|
||||
|
||||
setInterval(function(){
|
||||
redraw(canvas, gl, shader, fbo, fbo2, fbo3, depth, identity, unpremult, hblur, vblur, hdof, vdof);
|
||||
}, 33);
|
||||
}
|
||||
|
||||
function drawCube (gl, shader, angle, axis, x,y,z, s, va, na, ta) {
|
||||
Matrix.copyMatrix(look, vmat);
|
||||
Matrix.translate3InPlace(x,y,z,vmat);
|
||||
Matrix.scale1InPlace(s,vmat);
|
||||
Matrix.rotateInPlace(angle, axis, vmat);
|
||||
|
||||
// Note: we could just use mat3(MVMatrix) as the normal matrix
|
||||
// as MVMatrix has only rotations, translations and uniform scaling
|
||||
// <=> MVMatrix is a scaled orthonormal matrix
|
||||
// hence normalize(mat3(MVMatrix)*v) == normalize(mat3(transpose(inverse(MVMatrix))*v)
|
||||
//
|
||||
// But let's do it the hard way to see if Matrix.inverse3x3 works...
|
||||
Matrix.inverseTo3x3InPlace(vmat, nmat);
|
||||
Matrix.transpose3x3InPlace(nmat);
|
||||
|
||||
shader.uniformMatrix4fv("MVMatrix", vmat);
|
||||
shader.uniformMatrix3fv("NMatrix", nmat);
|
||||
|
||||
var cube = Cube.getCachedVBO(gl);
|
||||
cube.draw(va, na, ta);
|
||||
}
|
||||
|
||||
var carr = [];
|
||||
for (var i=0; i<25; i++) {
|
||||
carr.push([Math.random(), Math.random(), Math.random()]);
|
||||
}
|
||||
|
||||
function drawScene (gl, shader, va, na, ta) {
|
||||
var ot = new Date().getTime();
|
||||
var t = ot;
|
||||
|
||||
shader.uniformMatrix4fv("PMatrix", pmat);
|
||||
for (var i=0; i<carr.length; i++){
|
||||
var c = carr[i];
|
||||
var f = c[1] < 0.5 ? 1 : -1;
|
||||
var t = ot;
|
||||
drawCube(gl, shader,
|
||||
(t/(f*400*(c[0]+0.5))) % (2*Math.PI), c,
|
||||
|
||||
0.45+0.8*c[2],
|
||||
-0.4+Math.cos((i/carr.length*Math.PI*2)+t/1000),
|
||||
0.8+Math.sin((i/carr.length*Math.PI*2)+t/1000)*3.2,
|
||||
|
||||
0.05 + Math.pow((c[0]+c[1]+c[2])*0.33, 2)*0.3,
|
||||
va, na, ta);
|
||||
}
|
||||
}
|
||||
|
||||
var nmat = Matrix.newIdentity3x3();
|
||||
var vmat = Matrix.newIdentity();
|
||||
var vmat2 = Matrix.newIdentity();
|
||||
var pmat = null;
|
||||
var look = Matrix.lookAt([4,-1,8], [-0.2,0,0], [0,1,0]);
|
||||
var useDoF = false;
|
||||
|
||||
var firstFrame = true;
|
||||
|
||||
function redraw(canvas, gl, shader, fbo, fbo2, fbo3, depth, identity, unpremult, hblur, vblur, hdof, vdof) {
|
||||
|
||||
var doDoF = useDoF;
|
||||
gl.viewport(0, 0, canvas.width, canvas.height);
|
||||
gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
||||
gl.enable(gl.DEPTH_TEST);
|
||||
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||||
|
||||
fbo.use();
|
||||
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||||
|
||||
shader.use();
|
||||
|
||||
var va = shader.attrib("Vertex");
|
||||
var na = shader.attrib("Normal");
|
||||
var ta = shader.attrib("Tex");
|
||||
|
||||
if (pmat == null)
|
||||
pmat = Matrix.perspective(30, canvas.width/canvas.height, 1, 100);
|
||||
|
||||
shader.uniform4f("MaterialSpecular", 0.95, 0.9, 0.6, 1);
|
||||
shader.uniform4f("MaterialDiffuse", 0.50, 0.35, 0.35, 1);
|
||||
shader.uniform4f("MaterialAmbient", 0.0, 0.1, 0.2, 1);
|
||||
shader.uniform1f("MaterialShininess", 1.5);
|
||||
|
||||
shader.uniform4f("GlobalAmbient", 0.1, 0.1, 0.1, 1);
|
||||
|
||||
shader.uniform4f("LightPos", 1, 5, 3, 1.0);
|
||||
|
||||
shader.uniform4f("LightSpecular", 0.9, 0.9, 0.9, 1);
|
||||
shader.uniform4f("LightDiffuse", 0.8, 0.8, 0.8, 1);
|
||||
shader.uniform4f("LightAmbient", 0.0, 0.06, 0.2, 1);
|
||||
shader.uniform1f("LightConstantAtt", 0.0);
|
||||
shader.uniform1f("LightLinearAtt", 0.1);
|
||||
shader.uniform1f("LightQuadraticAtt", 0.0);
|
||||
|
||||
drawScene(gl, shader, va, na);
|
||||
|
||||
if (doDoF || firstFrame) {
|
||||
|
||||
fbo3.use();
|
||||
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||||
depth.use();
|
||||
var dva = depth.attrib("Vertex");
|
||||
|
||||
drawScene(gl, depth, dva);
|
||||
|
||||
gl.disable(gl.DEPTH_TEST);
|
||||
gl.activeTexture(gl.TEXTURE1);
|
||||
gl.bindTexture(gl.TEXTURE_2D, fbo3.texture);
|
||||
gl.activeTexture(gl.TEXTURE0);
|
||||
|
||||
|
||||
for (var i=0; i<3; i++) {
|
||||
fbo2.use();
|
||||
gl.bindTexture(gl.TEXTURE_2D, fbo.texture);
|
||||
|
||||
hdof.apply(function(f){
|
||||
f.uniform1i("Texture", 0);
|
||||
f.uniform1i("Depth", 1);
|
||||
f.uniform1f("iter", i);
|
||||
f.uniform1f("step", 1.0/canvas.width);
|
||||
});
|
||||
|
||||
fbo.use();
|
||||
gl.bindTexture(gl.TEXTURE_2D, fbo2.texture);
|
||||
|
||||
vdof.apply(function(f){
|
||||
f.uniform1i("Texture", 0);
|
||||
f.uniform1i("Depth", 1);
|
||||
f.uniform1f("iter", i);
|
||||
f.uniform1f("step", 1.0/canvas.width);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
firstFrame = false;
|
||||
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
|
||||
gl.activeTexture(gl.TEXTURE1);
|
||||
gl.bindTexture(gl.TEXTURE_2D, null);
|
||||
gl.activeTexture(gl.TEXTURE0);
|
||||
gl.bindTexture(gl.TEXTURE_2D, fbo.texture);
|
||||
|
||||
// The DoF blur blurs the color from the transparent black background with
|
||||
// the cubes. To get rid of the border, we can treat it as premultiplied alpha.
|
||||
// To see the problem, try replacing unpremult with identity.
|
||||
unpremult.apply(function(f){
|
||||
f.uniform1i("Texture", 0);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
window.addEventListener("load", init, false);
|
||||
</script>
|
||||
|
||||
<script id="ppix-vert" type="x-shader/x-vertex">
|
||||
attribute vec3 Vertex;
|
||||
attribute vec3 Normal;
|
||||
attribute vec2 Tex;
|
||||
|
||||
uniform mat4 PMatrix;
|
||||
uniform mat4 MVMatrix;
|
||||
uniform mat3 NMatrix;
|
||||
|
||||
uniform vec4 MaterialAmbient;
|
||||
uniform vec4 MaterialDiffuse;
|
||||
|
||||
uniform vec4 LightAmbient;
|
||||
uniform vec4 LightDiffuse;
|
||||
|
||||
uniform vec4 GlobalAmbient;
|
||||
|
||||
uniform vec4 LightPos;
|
||||
|
||||
varying vec4 diffuse, ambientGlobal, ambient;
|
||||
varying vec3 normal, lightDir, halfVector;
|
||||
varying float dist;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 worldPos;
|
||||
vec3 lightVector;
|
||||
vec4 v = vec4(Vertex, 1.0);
|
||||
|
||||
/* transform vertex normal into world space and normalize */
|
||||
normal = normalize(NMatrix * Normal);
|
||||
|
||||
/* transform vertex into world space and compute the vector
|
||||
from it to the light */
|
||||
worldPos = MVMatrix * v;
|
||||
lightVector = vec3(LightPos - worldPos);
|
||||
lightDir = normalize(lightVector);
|
||||
dist = length(lightVector);
|
||||
|
||||
/* Half-vector used in Blinn-Phong shading due to computational efficiency */
|
||||
halfVector = normalize(lightVector - vec3(worldPos));
|
||||
|
||||
diffuse = MaterialDiffuse * LightDiffuse;
|
||||
|
||||
/* The ambient terms have been separated since one of them */
|
||||
/* suffers attenuation */
|
||||
ambient = MaterialAmbient * LightAmbient;
|
||||
ambientGlobal = GlobalAmbient * MaterialAmbient;
|
||||
|
||||
gl_Position = PMatrix * worldPos;
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="ppix-frag" type="x-shader/x-fragment">
|
||||
precision mediump float;
|
||||
|
||||
uniform vec4 LightSpecular;
|
||||
uniform vec4 MaterialSpecular;
|
||||
uniform float MaterialShininess;
|
||||
|
||||
uniform float LightConstantAtt;
|
||||
uniform float LightLinearAtt;
|
||||
uniform float LightQuadraticAtt;
|
||||
|
||||
varying vec4 diffuse,ambientGlobal, ambient;
|
||||
varying vec3 normal, lightDir, halfVector;
|
||||
varying float dist;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 n, halfV, viewV, ldir;
|
||||
float NdotL, NdotHV;
|
||||
vec4 color = ambientGlobal;
|
||||
float att;
|
||||
|
||||
n = normalize(normal);
|
||||
|
||||
NdotL = max(dot(n, normalize(lightDir)), 0.0);
|
||||
|
||||
if (NdotL > 0.0) {
|
||||
|
||||
att = 1.0 / (LightConstantAtt + LightLinearAtt * dist + LightQuadraticAtt * dist * dist);
|
||||
|
||||
color += att * (diffuse * NdotL + ambient);
|
||||
|
||||
halfV = normalize(halfVector);
|
||||
NdotHV = max( dot(normal, halfV), 0.0 );
|
||||
|
||||
color += att * MaterialSpecular * LightSpecular * pow(NdotHV, MaterialShininess);
|
||||
}
|
||||
|
||||
gl_FragColor = color;
|
||||
}
|
||||
</script>
|
||||
<script id="depth-vert" type="x-shader/x-vertex">
|
||||
attribute vec3 Vertex;
|
||||
uniform mat4 PMatrix;
|
||||
uniform mat4 MVMatrix;
|
||||
varying float depth;
|
||||
void main()
|
||||
{
|
||||
gl_Position = PMatrix * (MVMatrix * vec4(Vertex, 1.0));
|
||||
depth = 1.0-(gl_Position.z / gl_Position.w);
|
||||
}
|
||||
</script>
|
||||
<script id="depth-frag" type="x-shader/x-fragment">
|
||||
precision mediump float;
|
||||
|
||||
varying float depth;
|
||||
void main()
|
||||
{
|
||||
vec4 c = vec4(depth, 0.0, 0.0, 1.0);
|
||||
gl_FragColor = c;
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="identity-vert" type="x-shader/x-vertex">
|
||||
attribute vec3 Vertex;
|
||||
attribute vec2 Tex;
|
||||
|
||||
varying vec4 texCoord0;
|
||||
void main()
|
||||
{
|
||||
texCoord0 = vec4(Tex,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>
|
||||
<script id="premult-frag" type="x-shader/x-fragment">
|
||||
precision mediump float;
|
||||
|
||||
uniform sampler2D Texture;
|
||||
|
||||
varying vec4 texCoord0;
|
||||
void main()
|
||||
{
|
||||
vec4 c = texture2D(Texture, texCoord0.st);
|
||||
float a = c.a;
|
||||
c *= a;
|
||||
c.a = a;
|
||||
gl_FragColor = c;
|
||||
}
|
||||
</script>
|
||||
<script id="unpremult-frag" type="x-shader/x-fragment">
|
||||
precision mediump float;
|
||||
|
||||
uniform sampler2D Texture;
|
||||
|
||||
varying vec4 texCoord0;
|
||||
void main()
|
||||
{
|
||||
vec4 c = texture2D(Texture, texCoord0.st);
|
||||
float a = c.a;
|
||||
c /= a;
|
||||
c.a = a;
|
||||
gl_FragColor = c;
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="hblur-frag" type="x-shader/x-fragment">
|
||||
precision mediump float;
|
||||
|
||||
uniform sampler2D Texture;
|
||||
uniform float step;
|
||||
float kernel[7] = float[](0.046, 0.111, 0.202, 0.283, 0.202, 0.111, 0.046);
|
||||
|
||||
varying vec4 texCoord0;
|
||||
void main()
|
||||
{
|
||||
int i=0;
|
||||
if (texture2D(Texture, texCoord0.st).a > 0.0) {
|
||||
vec4 sum = vec4(0.0);
|
||||
for (i=0; i<7; i++) {
|
||||
vec4 tmp = texture2D(Texture, texCoord0.st + vec2(i*step,0));
|
||||
sum += tmp * kernel[i];
|
||||
}
|
||||
gl_FragColor = sum;
|
||||
} else {
|
||||
gl_FragColor = texture2D(Texture, texCoord0.st);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script id="vblur-frag" type="x-shader/x-fragment">
|
||||
precision mediump float;
|
||||
|
||||
uniform sampler2D Texture;
|
||||
uniform float step;
|
||||
float kernel[7] = float[](0.046, 0.111, 0.202, 0.283, 0.202, 0.111, 0.046);
|
||||
|
||||
varying vec4 texCoord0;
|
||||
void main()
|
||||
{
|
||||
int i=0;
|
||||
if (texture2D(Texture, texCoord0.st).a > 0.0) {
|
||||
vec4 sum = vec4(0.0);
|
||||
for (i=0; i<7; i++) {
|
||||
vec4 tmp = texture2D(Texture, texCoord0.st + vec2(0,i*step));
|
||||
sum += tmp * kernel[i];
|
||||
}
|
||||
gl_FragColor = sum;
|
||||
} else {
|
||||
gl_FragColor = texture2D(Texture, texCoord0.st);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script id="hdof-frag" type="x-shader/x-fragment">
|
||||
precision mediump float;
|
||||
|
||||
uniform sampler2D Texture;
|
||||
uniform sampler2D Depth;
|
||||
uniform float step;
|
||||
uniform float iter;
|
||||
float kernel[7] = { 0.046, 0.111, 0.202, 0.283, 0.202, 0.111, 0.046 };
|
||||
|
||||
varying vec4 texCoord0;
|
||||
void main()
|
||||
{
|
||||
vec4 tmp;
|
||||
vec4 sum = vec4(0.0);
|
||||
bool b = (iter < -26.0+36.0*(1.0-texture2D(Depth, texCoord0.st).r) && texture2D(Texture, texCoord0.st).a > 0.0);
|
||||
tmp = texture2D(Texture, texCoord0.st + vec2(float(0-3)*step,0));
|
||||
sum += tmp * kernel[0];
|
||||
tmp = texture2D(Texture, texCoord0.st + vec2(float(1-3)*step,0));
|
||||
sum += tmp * kernel[1];
|
||||
tmp = texture2D(Texture, texCoord0.st + vec2(float(2-3)*step,0));
|
||||
sum += tmp * kernel[2];
|
||||
tmp = texture2D(Texture, texCoord0.st + vec2(float(3-3)*step,0));
|
||||
sum += tmp * kernel[3];
|
||||
tmp = texture2D(Texture, texCoord0.st + vec2(float(4-3)*step,0));
|
||||
sum += tmp * kernel[4];
|
||||
tmp = texture2D(Texture, texCoord0.st + vec2(float(5-3)*step,0));
|
||||
sum += tmp * kernel[5];
|
||||
tmp = texture2D(Texture, texCoord0.st + vec2(float(6-3)*step,0));
|
||||
sum += tmp * kernel[6];
|
||||
gl_FragColor = mix(texture2D(Texture, texCoord0.st), sum, b ? 1.0 : 0.0);
|
||||
}
|
||||
</script>
|
||||
<script id="vdof-frag" type="x-shader/x-fragment">
|
||||
precision mediump float;
|
||||
|
||||
uniform sampler2D Texture;
|
||||
uniform sampler2D Depth;
|
||||
uniform float step;
|
||||
uniform float iter;
|
||||
float kernel[7] = float[7](0.046, 0.111, 0.202, 0.283, 0.202, 0.111, 0.046);
|
||||
|
||||
varying vec4 texCoord0;
|
||||
void main()
|
||||
{
|
||||
vec4 tmp;
|
||||
vec4 sum = vec4(0.0);
|
||||
bool b = (iter < -26.0+36.0*(1.0-texture2D(Depth, texCoord0.st).r) && texture2D(Texture, texCoord0.st).a > 0.0);
|
||||
tmp = texture2D(Texture, texCoord0.st + vec2(0,float(0-3)*step));
|
||||
sum += tmp * kernel[0];
|
||||
tmp = texture2D(Texture, texCoord0.st + vec2(0,float(1-3)*step));
|
||||
sum += tmp * kernel[1];
|
||||
tmp = texture2D(Texture, texCoord0.st + vec2(0,float(2-3)*step));
|
||||
sum += tmp * kernel[2];
|
||||
tmp = texture2D(Texture, texCoord0.st + vec2(0,float(3-3)*step));
|
||||
sum += tmp * kernel[3];
|
||||
tmp = texture2D(Texture, texCoord0.st + vec2(0,float(4-3)*step));
|
||||
sum += tmp * kernel[4];
|
||||
tmp = texture2D(Texture, texCoord0.st + vec2(0,float(5-3)*step));
|
||||
sum += tmp * kernel[5];
|
||||
tmp = texture2D(Texture, texCoord0.st + vec2(0,float(6-3)*step));
|
||||
sum += tmp * kernel[6];
|
||||
gl_FragColor = mix(texture2D(Texture, texCoord0.st), sum, b ? 1.0 : 0.0);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
* { margin: 0px; padding: 0px; }
|
||||
html {
|
||||
background-color: #707888;
|
||||
color: #222222;
|
||||
}
|
||||
#canvas {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
top: 115px; left: 550px;
|
||||
}
|
||||
#note {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
left: 4px;
|
||||
}
|
||||
#content {
|
||||
margin-left: 99px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
padding-bottom: 16px;
|
||||
width: 600px;
|
||||
background-color: rgba(255,255,255,1.0);
|
||||
text-align: center;
|
||||
border-left: 1px solid rgba(0,0,0,0.5);
|
||||
border-right: 2px solid rgba(0,0,0,0.75);
|
||||
}
|
||||
h1 {
|
||||
padding-top: 24px;
|
||||
padding-bottom: 16px;
|
||||
margin-bottom: 24px;
|
||||
border-bottom: 1px solid black;
|
||||
font-family: Times New Roman, Serif;
|
||||
font-weight: bold;
|
||||
font-size: 40px;
|
||||
}
|
||||
#content p {
|
||||
text-indent: 24px;
|
||||
margin-left: 24px;
|
||||
margin-right: 32px;
|
||||
text-align: justify;
|
||||
font-family: Serif;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
#above {
|
||||
position: absolute;
|
||||
top: 300px;
|
||||
left: 716px;
|
||||
padding: 10px 20px;
|
||||
background-color: rgba(0,225,0,0.5);
|
||||
border-left: 2px solid rgba(0,64,0,0.75);
|
||||
color: white;
|
||||
font-size: small;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
#above p {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
</head><body>
|
||||
<canvas id="canvas" width="400" height="400" title="Click to toggle DOF shader" onclick="useDoF = !useDoF"></canvas>
|
||||
<pre id="note"></pre>
|
||||
|
||||
<div id="content">
|
||||
<h1>OpenGL for the web</h1>
|
||||
<p>
|
||||
The WebGL specification gives web developers access to an
|
||||
OpenGL ES 2.0 drawing context for the canvas tag. What that means is
|
||||
that you can finally harness the power of the GPU for awesome visuals
|
||||
and heavy-duty number crunching in your web apps. </p><p> OpenGL ES 2.0 is a subset of OpenGL 2.0 aimed at embedded
|
||||
devices and game consoles. As such, it's a very minimalistic low-level
|
||||
API, even more so than desktop OpenGL. In fact, if you took desktop
|
||||
OpenGL and stripped out everything but shaders, vertex arrays and
|
||||
textures, you'd get something quite like OpenGL ES 2.0. </p>
|
||||
<p>
|
||||
As there is no fixed-function pipeline, you need to write GLSL shaders to draw <i>anything</i>.
|
||||
And you need to do your own transformation math, including keeping
|
||||
track of the transformation matrix stack. So the raw API is really not
|
||||
for the faint of heart; you do need to know your 3D math and shading
|
||||
equations. </p>
|
||||
<p> For example, to draw the spinning cubes on the
|
||||
right - around 200 lines of application code, 250 lines of shaders and
|
||||
800 lines of library code - I had to scrounge the internet for <a href="http://www.lighthouse3d.com/opengl/glsl/index.php?pointlight">GLSL shaders</a>
|
||||
to do the transformation and lighting, write a small matrix math
|
||||
library in JavaScript and a DOF blur shader. While highly educational,
|
||||
it was also a rather steep hill to climb. </p>
|
||||
<p> So, the intended audience of the raw context
|
||||
interface are not really end-users, but library developers who can
|
||||
write easy-to-use interfaces to the functionality, and 3D developers
|
||||
who require a high level of control over the rendering pipeline. </p>
|
||||
<p> The really cool thing about the OpenGL Canvas is
|
||||
that it doesn't make policy decisions. There's no single set-in-stone
|
||||
use case for it: In addition to 3D graphics, you can also use it for
|
||||
filtering images, visualizing fluid dynamics, doing real-time video
|
||||
effects, or just crunching a whole lot of FP math. If you can do it on
|
||||
the GPU, you're in luck! </p>
|
||||
</div>
|
||||
<div id="above">
|
||||
<p>You can also place content above the canvas</p>
|
||||
</div>
|
||||
</body></html>
|
|
@ -1,163 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<!--
|
||||
|
||||
/*
|
||||
** Copyright (c) 2012 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
-->
|
||||
<script type="application/javascript" src="../util.js"></script>
|
||||
<script>
|
||||
"use strict";
|
||||
var processor = {
|
||||
lastTime : new Date,
|
||||
timerCallback: function() {
|
||||
if (this.video.paused || this.video.ended) {
|
||||
return;
|
||||
}
|
||||
this.computeFrame();
|
||||
var t = new Date;
|
||||
var elapsed = t - this.lastTime;
|
||||
this.lastTime = t;
|
||||
var self = this;
|
||||
setTimeout(function () {
|
||||
self.timerCallback();
|
||||
}, Math.max(0, 33-elapsed));
|
||||
},
|
||||
|
||||
init: function() {
|
||||
if (this.initDone) return;
|
||||
this.c2 = document.getElementById("c2");
|
||||
this.ctx2 = getGLContext(this.c2);
|
||||
this.greenScreen = new Filter(this.ctx2, 'identity-flip-vert', 'greenScreen');
|
||||
this.ctx2.activeTexture(this.ctx2.TEXTURE0);
|
||||
this.tex = loadTexture(this.ctx2, this.c1, false);
|
||||
this.ctx2.activeTexture(this.ctx2.TEXTURE1);
|
||||
this.tex2 = loadTexture(this.ctx2, document.getElementById('i'), false);
|
||||
this.ctx2.activeTexture(this.ctx2.TEXTURE0);
|
||||
this.initDone = true;
|
||||
},
|
||||
|
||||
doLoad: function() {
|
||||
this.video = document.getElementById("video");
|
||||
this.c1 = document.getElementById("c1");
|
||||
this.ctx1 = this.c1.getContext("2d");
|
||||
this.ctx1.globalCompositeOperation = 'copy';
|
||||
this.ctx1.fillRect(0,0,this.c1.width, this.c1.height);
|
||||
var self = this;
|
||||
this.video.addEventListener("play", function() {
|
||||
self.init();
|
||||
self.width = self.video.videoWidth;
|
||||
self.height = self.video.videoHeight;
|
||||
self.lastTime = new Date;
|
||||
self.timerCallback();
|
||||
}, false);
|
||||
},
|
||||
|
||||
computeFrame: function() {
|
||||
// this.ctx1.drawImage(this.video, 0, 0, this.width, this.height);
|
||||
this.ctx2.texImage2D(this.ctx2.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.video);
|
||||
this.greenScreen.apply(function(s) {
|
||||
s.uniform1i('Texture', 0);
|
||||
s.uniform1i('Texture2', 1);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
</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="greenScreen" type="x-shader/x-fragment">
|
||||
precision mediump float;
|
||||
|
||||
uniform sampler2D Texture;
|
||||
uniform sampler2D Texture2;
|
||||
|
||||
varying vec4 texCoord0;
|
||||
void main()
|
||||
{
|
||||
vec4 c = texture2D(Texture, texCoord0.st);
|
||||
float r = c.r * 0.5;
|
||||
float a = c.g * 6.28;
|
||||
float x = cos(a) * r;
|
||||
float y = sin(a) * r;
|
||||
vec4 c2 = texture2D(Texture2, vec2(0.7+x, 0.5+y));
|
||||
// Shaders with branches are not allowed when dealing with non-SOP content
|
||||
// so instead of "if (b) c2.a = 0;", we use mix()
|
||||
bool b = (c.g > 120.0/255.0 && c.r > 120.0/255.0 && c.b < 50.0/255.0);
|
||||
c2.a = mix(c2.a, 0.0, float(b));
|
||||
gl_FragColor = c2;
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
body {
|
||||
background: black;
|
||||
color:#CCCCCC;
|
||||
}
|
||||
a {
|
||||
color: white;
|
||||
}
|
||||
#c2 {
|
||||
background-image: url(http://www.mozbox.org/pub/green/foo.png);
|
||||
background-repeat: repeat;
|
||||
}
|
||||
div {
|
||||
float: left;
|
||||
border :1px solid #444444;
|
||||
padding:10px;
|
||||
margin: 10px;
|
||||
background:#3B3B3B;
|
||||
}
|
||||
img { display: none; }
|
||||
</style>
|
||||
</head>
|
||||
<body onload="processor.doLoad()">
|
||||
<div>
|
||||
This is a port of Paul Rouget's <a href="http://blog.mozbox.org/post/2009/02/25/video-canvas%3A-special-effects">Canvas+Video green screen demo</a>, plus a texture lookup from the Firefox logo based on the values of the green and red color channels.
|
||||
</div>
|
||||
<div>
|
||||
<video id="video" controls="true">
|
||||
<source src="http://www.mozbox.org/pub/green/video.ogv"></source>
|
||||
<source src="http://cs.helsinki.fi/u/ilmarihe/c3d/demos/video.mp4"></source>
|
||||
</video>
|
||||
<canvas id="c1" width="320" height="192"></canvas>
|
||||
</div>
|
||||
<div>
|
||||
<canvas id="c2" width="640" height="384"></canvas>
|
||||
</div>
|
||||
<img id="i" src="http://www.mozbox.org/pub/green/foo.png">
|
||||
</body>
|
||||
</html>
|
|
@ -67,8 +67,14 @@ Tests.testBufferData = function(gl) {
|
|||
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 too large",
|
||||
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');
|
||||
|
|
|
@ -89,16 +89,12 @@ Tests.testDrawArraysVBOMulti = function(gl, prog, v,n,t) {
|
|||
assertOk(function(){gl.drawArrays(gl.TRIANGLES, 0, 2);});
|
||||
assertOk(function(){gl.drawArrays(gl.TRIANGLES, 0, 6);});
|
||||
assertOk(function(){gl.drawArrays(gl.TRIANGLES, 1, 5);});
|
||||
assertFail(function(){gl.drawArrays(gl.TRIANGLES, 1, 6);});
|
||||
assertFail(function(){gl.drawArrays(gl.TRIANGLES, 6, 1);});
|
||||
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);});
|
||||
assertFail(function(){gl.drawArrays(gl.TRIANGLES, 1, 6);});
|
||||
assertFail(function(){gl.drawArrays(gl.TRIANGLES, 6, 1);});
|
||||
vbo.destroy();
|
||||
assert(0 == checkError(gl, "vbo.destroy"));
|
||||
}
|
||||
|
|
|
@ -1,305 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<!--
|
||||
|
||||
/*
|
||||
** Copyright (c) 2012 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
-->
|
||||
<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 vertsA = new Float32Array(verts);
|
||||
var normalsA = new Float32Array(normals);
|
||||
var texcoordsA = new Float32Array(texcoords);
|
||||
|
||||
Tests.startUnit = function () {
|
||||
var canvas = document.getElementById('gl');
|
||||
var gl = wrapGLContext(getGLContext(canvas));
|
||||
var prog = new Shader(gl, 'vert', 'frag');
|
||||
prog.use();
|
||||
var v = prog.attrib('Vertex');
|
||||
var n = prog.attrib('Normal');
|
||||
var t = prog.attrib('Tex');
|
||||
return [gl,prog,v,n,t];
|
||||
}
|
||||
|
||||
Tests.setup = function(gl, prog, v,n,t) {
|
||||
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.testDrawArraysEmpty = function(gl, prog, v,n,t) {
|
||||
var b = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, b);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([]), gl.STATIC_DRAW);
|
||||
assertOk(function(){gl.vertexAttribPointer(v, 3, gl.FLOAT, false, 0, 0);})
|
||||
gl.enableVertexAttribArray(v);
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "zero size array",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 0, 1);});
|
||||
gl.deleteBuffer(b);
|
||||
}
|
||||
|
||||
Tests.testDrawArraysOutOfBounds = function(gl, prog, v,n,t) {
|
||||
var b = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, b);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([]), gl.STATIC_DRAW);
|
||||
assertOk(function(){gl.vertexAttribPointer(v, 3, gl.FLOAT, false, 0, 0);});
|
||||
gl.enableVertexAttribArray(v);
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "zero size array",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 0, 1);});
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "zero size array 10000",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 0, 10000);});
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "zero size array 10000000000000",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 0, 10000000000000);});
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "zero size array fraction",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 0, 1.6);});
|
||||
assertGLError(gl, gl.INVALID_VALUE, "negative offset",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 0, -1);});
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "count out of range",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 0, 1);});
|
||||
assertGLError(gl, gl.INVALID_VALUE, "negative count",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 0, -1);});
|
||||
assertGLError(gl, gl.INVALID_VALUE, "positive count, negative offset",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, -1, 1);});
|
||||
assertGLError(gl, gl.INVALID_VALUE, "negative count, positive offset",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 1, -1);});
|
||||
gl.deleteBuffer(b);
|
||||
}
|
||||
|
||||
|
||||
Tests.testDrawArraysWithDataOutOfBounds = function(gl, prog, v,n,t) {
|
||||
var b = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, b);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, vertsA, gl.STATIC_DRAW);
|
||||
gl.vertexAttribPointer(v, 3, gl.FLOAT, false, 0, 0);
|
||||
gl.enableVertexAttribArray(v);
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "3 element array",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 3, 2);});
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "3 element array 10000",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 0, 10000);});
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "3 element array 10000000000000",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 0, 10000000000000);});
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "fractional count",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 3, 1.6);});
|
||||
assertGLError(gl, gl.INVALID_VALUE, "negative offset",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 0, -1);});
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "count out of range",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 0, 4);});
|
||||
assertGLError(gl, gl.INVALID_VALUE, "negative count",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 0, -1);});
|
||||
assertGLError(gl, gl.INVALID_VALUE, "positive count, negative offset",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, -1, 2);});
|
||||
assertGLError(gl, gl.INVALID_VALUE, "negative count, positive offset",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 1, -1);});
|
||||
gl.deleteBuffer(b);
|
||||
}
|
||||
|
||||
Tests.testDrawArraysMultiOutOfBounds = function(gl, prog, v,n,t) {
|
||||
var bs = [];
|
||||
bs.push(gl.createBuffer());
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, bs[bs.length-1]);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, vertsA, gl.STATIC_DRAW);
|
||||
gl.vertexAttribPointer(v, 3, gl.FLOAT, false, 0, 0);
|
||||
bs.push(gl.createBuffer());
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, bs[bs.length-1]);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, normalsA, gl.STATIC_DRAW);
|
||||
gl.vertexAttribPointer(n, 3, gl.FLOAT, false, 0, 0);
|
||||
bs.push(gl.createBuffer());
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, bs[bs.length-1]);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, texcoordsA, gl.STATIC_DRAW);
|
||||
gl.vertexAttribPointer(t, 2, gl.FLOAT, false, 0, 0);
|
||||
gl.enableVertexAttribArray(v);
|
||||
gl.enableVertexAttribArray(n);
|
||||
gl.enableVertexAttribArray(t);
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "multi array 1",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 3, 2);});
|
||||
bs.push(gl.createBuffer());
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, bs[bs.length-1]);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verts.concat(verts)), gl.STATIC_DRAW);
|
||||
bs.push(gl.createBuffer());
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, bs[bs.length-1]);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(texcoords.concat(texcoords)), gl.STATIC_DRAW);
|
||||
gl.vertexAttribPointer(v, 3, gl.FLOAT, false, 0, 0);
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, bs[1]);
|
||||
gl.vertexAttribPointer(n, 3, gl.FLOAT, false, 0, 0);
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, bs[2]);
|
||||
gl.vertexAttribPointer(t, 2, gl.FLOAT, false, 0, 0);
|
||||
gl.enableVertexAttribArray(v);
|
||||
gl.enableVertexAttribArray(n);
|
||||
gl.enableVertexAttribArray(t);
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "multi array 2",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 3, 2);});
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "multi array 3",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 4, 2);});
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, bs[0]);
|
||||
gl.vertexAttribPointer(v, 3, gl.FLOAT, false, 0, 0);
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, bs[3]);
|
||||
gl.vertexAttribPointer(n, 3, gl.FLOAT, false, 0, 0);
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, bs[2]);
|
||||
gl.vertexAttribPointer(t, 2, gl.FLOAT, false, 0, 0);
|
||||
gl.enableVertexAttribArray(v);
|
||||
gl.enableVertexAttribArray(n);
|
||||
gl.enableVertexAttribArray(t);
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "multi array 4",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 3, 2);});
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "multi array 5",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 4, 2);});
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, bs[0]);
|
||||
gl.vertexAttribPointer(v, 3, gl.FLOAT, false, 0, 0);
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, bs[1]);
|
||||
gl.vertexAttribPointer(n, 3, gl.FLOAT, false, 0, 0);
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, bs[4]);
|
||||
gl.vertexAttribPointer(t, 2, gl.FLOAT, false, 0, 0);
|
||||
gl.enableVertexAttribArray(v);
|
||||
gl.enableVertexAttribArray(n);
|
||||
gl.enableVertexAttribArray(t);
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "multi array 6",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 3, 2);});
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "multi array 7",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 3, 2);});
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, bs[3]);
|
||||
gl.vertexAttribPointer(v, 3, gl.FLOAT, false, 0, 0);
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, bs[3]);
|
||||
gl.vertexAttribPointer(n, 3, gl.FLOAT, false, 0, 0);
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, bs[2]);
|
||||
gl.vertexAttribPointer(t, 2, gl.FLOAT, false, 0, 0);
|
||||
gl.enableVertexAttribArray(v);
|
||||
gl.enableVertexAttribArray(n);
|
||||
gl.enableVertexAttribArray(t);
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "multi array 8",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 4, 1);});
|
||||
assertGLError(gl, gl.INVALID_VALUE, "negative count",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, -1, 2);});
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "zero count???",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 0, 4);});
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "multi array 9",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 1, 4);});
|
||||
bs.forEach(function(b){ gl.deleteBuffer(b) });
|
||||
}
|
||||
|
||||
|
||||
Tests.testDrawArraysVBOOutOfBounds = function(gl, prog, v,n,t) {
|
||||
var vbo = new VBO(gl, {size:3, data:Quad.vertices});
|
||||
vbo.use(v);
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "1",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 6, 1);});
|
||||
assertGLError(gl, gl.INVALID_VALUE, "negative count",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 2, -1);});
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "3",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 0, 7);});
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "4",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 1, 6);});
|
||||
vbo.destroy();
|
||||
}
|
||||
|
||||
Tests.testDrawArraysVBOMultiOutOfBounds = 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.use(v, n, t);
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "1",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 6, 1);});
|
||||
assertGLError(gl, gl.INVALID_VALUE, "negative count",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 2, -1);});
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "2",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 0, 7);});
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "3",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 1, 6);});
|
||||
vbo.destroy();
|
||||
}
|
||||
|
||||
Tests.testDrawArraysOOBShaderJuggle = function(gl, prog, v,n,t) {
|
||||
var vbo = new VBO(gl,
|
||||
{size:3, data:[0,0,0]},
|
||||
{size:3, data:[0,0,0,0,0,0]});
|
||||
vbo.init();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, vbo.vbos[0]);
|
||||
gl.vertexAttribPointer(v, 3, gl.FLOAT, false, 0, 0);
|
||||
gl.enableVertexAttribArray(v);
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "offset too big",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 0, 2);});
|
||||
var sh2 = new Shader(gl, 'vert', 'frag');
|
||||
sh2.use();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, vbo.vbos[1]);
|
||||
gl.vertexAttribPointer(sh2.attrib('Vertex'), 3, gl.FLOAT, false, 0, 0);
|
||||
gl.enableVertexAttribArray(sh2.attrib('Vertex'));
|
||||
assertOk(function(){gl.drawArrays(gl.TRIANGLES, 0, 2);});
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "offset too big 2",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 0, 3);});
|
||||
prog.use();
|
||||
gl.vertexAttribPointer(prog.attrib('Vertex'), 3, gl.FLOAT, false, 0, 0);
|
||||
gl.enableVertexAttribArray(prog.attrib('Vertex'));
|
||||
assertOk(function(){gl.drawArrays(gl.TRIANGLES, 0, 2);});
|
||||
assertGLError(gl, gl.INVALID_OPERATION, "offset too big 3",
|
||||
function(){gl.drawArrays(gl.TRIANGLES, 0, 3);});
|
||||
sh2.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()
|
||||
{
|
||||
gl_FragColor = texCoord0;
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style>canvas{ position:absolute; }</style>
|
||||
</head><body>
|
||||
<canvas id="gl" width="1" height="1"></canvas>
|
||||
</body></html>
|
|
@ -94,6 +94,25 @@ Tests.testTexImage2D = function(gl) {
|
|||
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);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -103,6 +103,25 @@ Tests.testTexImage2D = function(gl) {
|
|||
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);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,253 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<!--
|
||||
|
||||
/*
|
||||
** Copyright (c) 2012 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
-->
|
||||
<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.autorun = false;
|
||||
Tests.message = "Caution: might hang your GPU"
|
||||
|
||||
var arr = ['whiletrue', 'loop100M', 'loopComp', 'variable'];
|
||||
arr.forEach(function(e){
|
||||
Tests['test'+e+'vert'] = function(gl) {
|
||||
var sh = new Filter(gl, e+'vert', 'frag');
|
||||
assertOk(function(){
|
||||
sh.apply();
|
||||
});
|
||||
sh.destroy();
|
||||
}
|
||||
Tests['test'+e+'frag'] = function(gl) {
|
||||
var sh = new Filter(gl, 'vert', e+'frag');
|
||||
assertOk(function(){
|
||||
sh.apply();
|
||||
});
|
||||
sh.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
Tests.testMandelbrot = function(gl) {
|
||||
gl.disable(gl.DEPTH_TEST);
|
||||
var sh = new Filter(gl, 'identity-vert', 'mandelbrot-frag');
|
||||
sh.apply(function(s){
|
||||
s.uniform1f('z', 0.15);
|
||||
s.uniform1f('x', -1.25);
|
||||
});
|
||||
for (var i=0; i<256; i++) {
|
||||
sh.apply();
|
||||
}
|
||||
sh.destroy();
|
||||
}
|
||||
|
||||
</script>
|
||||
<script id="identity-vert" type="x-shader/x-vertex">
|
||||
|
||||
attribute vec3 Vertex;
|
||||
attribute vec2 Tex;
|
||||
|
||||
varying vec2 texCoord0;
|
||||
void main()
|
||||
{
|
||||
texCoord0 = vec2(Tex.s, Tex.t);
|
||||
gl_Position = vec4(Vertex, 1.0);
|
||||
}
|
||||
</script>
|
||||
<script id="mandelbrot-frag" type="x-shader/x-fragment">
|
||||
precision mediump float;
|
||||
|
||||
uniform float x,y,z;
|
||||
varying vec2 texCoord0;
|
||||
vec4 iter_z(float cr, float ci) {
|
||||
int i;
|
||||
float nzr, nzi, zr = 0.0, zi = 0.0;
|
||||
vec4 color = vec4(0.0);
|
||||
for (i=0; i<2500; i++) {
|
||||
nzr = zr * zr - zi * zi + cr;
|
||||
nzi = 2.0 * zr * zi + ci;
|
||||
zr = nzr;
|
||||
zi = nzi;
|
||||
}
|
||||
color = vec4(zi);
|
||||
color.a = 1.0;
|
||||
return color;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = iter_z(x+z*(2.0*texCoord0.s-1.5), y+z*(2.0*texCoord0.t-1.0));
|
||||
}
|
||||
</script>
|
||||
<script id="whiletruevert" type="x-shader/x-vertex">
|
||||
|
||||
|
||||
attribute vec3 Vertex; attribute vec2 Tex;
|
||||
varying vec2 TexCoord;
|
||||
void main()
|
||||
{
|
||||
float z = 1.0;
|
||||
while(true) { z += 0.1; z *= 0.995; }
|
||||
TexCoord = Tex.st;
|
||||
gl_Position = vec4(Vertex, z);
|
||||
}
|
||||
</script>
|
||||
<script id="loop100Mvert" type="x-shader/x-vertex">
|
||||
|
||||
|
||||
attribute vec3 Vertex; attribute vec2 Tex;
|
||||
varying vec2 TexCoord;
|
||||
void main()
|
||||
{
|
||||
int i;
|
||||
float z = 1.0;
|
||||
for (i = 0; i<1000000000; i++) {
|
||||
z += 0.1; z *= 0.995;
|
||||
}
|
||||
TexCoord = Tex.st;
|
||||
gl_Position = vec4(Vertex, z);
|
||||
}
|
||||
</script>
|
||||
<script id="loopCompvert" type="x-shader/x-vertex">
|
||||
|
||||
|
||||
attribute vec3 Vertex; attribute vec2 Tex;
|
||||
varying vec2 TexCoord;
|
||||
void main()
|
||||
{
|
||||
float z = 1.0;
|
||||
while(z > 0.0) { z += 0.1; z *= 0.995; }
|
||||
TexCoord = Tex.st;
|
||||
gl_Position = vec4(Vertex, z);
|
||||
}
|
||||
</script>
|
||||
<script id="variablevert" type="x-shader/x-vertex">
|
||||
|
||||
|
||||
attribute vec3 Vertex; attribute vec2 Tex;
|
||||
varying vec2 TexCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
float z = 1.0;
|
||||
while(z > Vertex.z) { z += 0.1; z *= 0.995; }
|
||||
TexCoord = Tex.st;
|
||||
gl_Position = vec4(Vertex, z);
|
||||
}
|
||||
</script>
|
||||
<script id="vert" type="x-shader/x-vertex">
|
||||
|
||||
|
||||
attribute vec3 Vertex; attribute vec2 Tex;
|
||||
varying vec2 TexCoord;
|
||||
void main()
|
||||
{
|
||||
TexCoord = Tex.st;
|
||||
gl_Position = vec4(Vertex, 0.0);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="whiletruefrag" type="x-shader/x-fragment">
|
||||
|
||||
|
||||
precision mediump float;
|
||||
|
||||
varying vec2 TexCoord;
|
||||
void main()
|
||||
{
|
||||
float z = 1.0;
|
||||
while(true) { z += 0.1; z *= 0.995; }
|
||||
gl_FragColor = vec4(1.0, TexCoord.s, TexCoord.t, z);
|
||||
}
|
||||
</script>
|
||||
<script id="loop100Mfrag" type="x-shader/x-fragment">
|
||||
|
||||
|
||||
precision mediump float;
|
||||
|
||||
varying vec2 TexCoord;
|
||||
void main()
|
||||
{
|
||||
int i;
|
||||
float z = 1.0;
|
||||
for (i = 0; i<1000000000; i++) {
|
||||
z += 0.1; z *= 0.995;
|
||||
}
|
||||
gl_FragColor = vec4(1.0, TexCoord.s, TexCoord.t, z);
|
||||
}
|
||||
</script>
|
||||
<script id="loopCompfrag" type="x-shader/x-fragment">
|
||||
|
||||
|
||||
precision mediump float;
|
||||
|
||||
varying vec2 TexCoord;
|
||||
void main()
|
||||
{
|
||||
float z = TexCoord.s;
|
||||
while(z > 0.0) { z += 0.1; z *= 0.995; }
|
||||
gl_FragColor = vec4(1.0, TexCoord.s, TexCoord.t, z);
|
||||
}
|
||||
</script>
|
||||
<script id="variablefrag" type="x-shader/x-fragment">
|
||||
|
||||
|
||||
precision mediump float;
|
||||
|
||||
varying vec2 TexCoord;
|
||||
void main()
|
||||
{
|
||||
float z = 1.0;
|
||||
while(z > TexCoord.s) { z += 0.1; z *= 0.995; }
|
||||
gl_FragColor = vec4(1.0, TexCoord.s, TexCoord.t, z);
|
||||
}
|
||||
</script>
|
||||
<script id="frag" type="x-shader/x-fragment">
|
||||
|
||||
|
||||
precision mediump float;
|
||||
|
||||
varying vec2 TexCoord;
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = vec4(1.0, TexCoord.s, TexCoord.t, 1.0);
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style>canvas{ position:absolute; }</style>
|
||||
</head><body>
|
||||
<canvas id="gl" width="512" height="512"></canvas>
|
||||
</body></html>
|
|
@ -1,115 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<!--
|
||||
|
||||
/*
|
||||
** Copyright (c) 2012 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
-->
|
||||
<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 = "Caution: may crash the browser";
|
||||
|
||||
Tests.startUnit = function () {
|
||||
var canvas = document.getElementById('gl');
|
||||
var gl = getGLContext(canvas);
|
||||
return [gl];
|
||||
}
|
||||
|
||||
Tests.testPassingTooManyVBOs = function(gl) {
|
||||
var sh = new Filter(gl, 'vert', 'frag');
|
||||
assertFail(function(){sh.apply();});
|
||||
sh.destroy();
|
||||
}
|
||||
Tests.testPassingTooManyUniforms = function(gl) {
|
||||
var sh = new Filter(gl, 'vert2', 'frag2');
|
||||
sh.apply(function(f){
|
||||
assertFail(function(){f.uniform1f('foo', 3.0);throwError("foo")});
|
||||
f.uniform1f('bar', 1.0);
|
||||
assertFail(function(){f.uniform1f('baz', 1.0);throwError("baz")});
|
||||
});
|
||||
sh.destroy();
|
||||
}
|
||||
|
||||
</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, 0.0);
|
||||
}
|
||||
</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>
|
||||
<script id="vert2" type="x-shader/x-vertex">
|
||||
|
||||
|
||||
uniform float foo, bar;
|
||||
attribute vec3 Vertex; attribute vec2 Tex;
|
||||
varying vec2 TexCoord;
|
||||
void main()
|
||||
{
|
||||
TexCoord = Tex.st;
|
||||
gl_Position = vec4(Vertex, bar);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="frag2" type="x-shader/x-fragment">
|
||||
|
||||
|
||||
precision mediump float;
|
||||
|
||||
uniform float baz;
|
||||
|
||||
varying vec2 TexCoord;
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = vec4(1.0, TexCoord.s, 0.0, 1.0);
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style>canvas{ position:absolute; }</style>
|
||||
</head><body>
|
||||
<canvas id="gl" width="1" height="1"></canvas>
|
||||
</body></html>
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -1,85 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<!--
|
||||
|
||||
/*
|
||||
** Copyright (c) 2012 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
-->
|
||||
<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.testInterval = function() {
|
||||
document.getElementById('dtMax').textContent = "Running, please wait...";
|
||||
setTimeout(function() {
|
||||
var t0 = new Date().getTime();
|
||||
var t = t0;
|
||||
var dtMax = 0;
|
||||
var frames = [];
|
||||
var iv;
|
||||
iv = setInterval(function() {
|
||||
if (t > t0 + 10000) {
|
||||
var hist = [];
|
||||
var dtMed = 0, maxi = [0, 0];
|
||||
for (var i=0; i<dtMax; i++) hist[i] = 0;
|
||||
for (var i=0; i<frames.length; i++)
|
||||
hist[frames[i]]++;
|
||||
for (var i=0; i<hist.length; i++)
|
||||
if (hist[i] > maxi[1]) maxi = [i, hist[i]];
|
||||
dtMed = maxi[0];
|
||||
var dtAvg = frames.reduce(function(s,i){return s + i;})/frames.length;
|
||||
document.getElementById('dtMax').textContent = "Longest frame: " + dtMax + " ms. Average frame: " + Math.floor(dtAvg*100)*0.01 + " ms. Median frame: " + dtMed + " ms.";
|
||||
clearInterval(iv);
|
||||
var c = document.getElementById('dtCanvas');
|
||||
c.width = frames.length;
|
||||
c.height = dtMax;
|
||||
var ctx = c.getContext('2d');
|
||||
for (var i=0; i<frames.length; i++)
|
||||
ctx.fillRect(i,0,1,frames[i]);
|
||||
}
|
||||
var t1 = new Date().getTime();
|
||||
if (t1-t > dtMax) dtMax = t1-t;
|
||||
frames.push(t1-t);
|
||||
t = t1;
|
||||
var rot = Matrix.rotate((t/400) % (2*Math.PI), [0, 1+(t%1000), 1]);
|
||||
var trans = Matrix.translate3(0, Math.cos(t/1000)*1, Math.sin(t/1000)*3);
|
||||
for (var i=0; i<200; i++)
|
||||
var mat = Matrix.mul4x4(rot, trans);
|
||||
}, 16);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
</script>
|
||||
<style>canvas{ position:absolute; }</style>
|
||||
</head><body>
|
||||
<h3>10 seconds of 60fps 200x mul4x4, frame time statistics</h3>
|
||||
<p id="dtMax"></p>
|
||||
<canvas id="dtCanvas"></canvas>
|
||||
</body></html>
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<!--
|
||||
|
||||
/*
|
||||
** Copyright (c) 2012 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
-->
|
||||
<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 might take a second or two (or ten)";
|
||||
|
||||
Tests.testMatrixMultiply = function() {
|
||||
time("testMatrixMultiply", function() {
|
||||
var mat = Matrix.identity;
|
||||
for (var i=0; i<1000000; i++)
|
||||
Matrix.mul4x4(mat, mat);
|
||||
});
|
||||
}
|
||||
Tests.testTransformStack = function() {
|
||||
time("testTransformStack", function() {
|
||||
var j = 0;
|
||||
for (var i=0; i<1000; i++) {
|
||||
var t = new Date().getTime();
|
||||
var pmat = Matrix.perspective(30, 600/400, 1, 100+(t%1000));
|
||||
var look = Matrix.lookAt([4,-1,8], [-0.2,0+(t%1000),0], [0,1,0]);
|
||||
var rot = Matrix.rotate((t/400) % (2*Math.PI), [0, 1+(t%1000), 1]);
|
||||
var trans = Matrix.translate3(0, Math.cos(t/1000)*1, Math.sin(t/1000)*3);
|
||||
var sca = Matrix.scale1(0.6+(t%1000));
|
||||
var vmat = Matrix.identity;
|
||||
vmat = Matrix.mul4x4(vmat, pmat);
|
||||
vmat = Matrix.mul4x4(vmat, look);
|
||||
vmat = Matrix.mul4x4(vmat, trans);
|
||||
vmat = Matrix.mul4x4(vmat, sca);
|
||||
vmat = Matrix.mul4x4(vmat, rot);
|
||||
j += vmat.length;
|
||||
}
|
||||
Tests.j = j;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
<style>canvas{ position:absolute; }</style>
|
||||
</head><body>
|
||||
<h3>1000000x JavaScript Matrix.mul4x4</h3>
|
||||
<p id="testMatrixMultiply"></p>
|
||||
<h3>1000x JavaScript transform stack</h3>
|
||||
<p id="testTransformStack"></p>
|
||||
</body></html>
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<!--
|
||||
|
||||
/*
|
||||
** Copyright (c) 2012 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
-->
|
||||
<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 might take a second or two";
|
||||
|
||||
Tests.testGLOverhead = function() {
|
||||
var gl = document.getElementById("gl").getContext(GL_CONTEXT_ID);
|
||||
var fakeGl = {getError: function(){ return 0; }};
|
||||
time("testGLOverhead", function() {
|
||||
for (var i=0; i<1000000; i++)
|
||||
gl.getError();
|
||||
});
|
||||
time("testJSOverhead", function() {
|
||||
for (var i=0; i<1000000; i++)
|
||||
fakeGl.getError();
|
||||
});
|
||||
time("testLoopOverhead", function() {
|
||||
for (var i=0; i<1000000;)
|
||||
i++;
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
<style>canvas{ position:absolute; }</style>
|
||||
</head><body>
|
||||
<canvas id="gl" width="16" height="16"></canvas>
|
||||
<h3>1000000x gl.getError() (measuring JS->GL call overhead)</h3>
|
||||
<p id="testGLOverhead"></p>
|
||||
<h3>1000000x fakeGl.getError() (measuring JS->JS call overhead)</h3>
|
||||
<p id="testJSOverhead"></p>
|
||||
<h3>1000000x i++ (measuring loop overhead)</h3>
|
||||
<p id="testLoopOverhead"></p>
|
||||
</body></html>
|
||||
|
|
@ -1097,6 +1097,24 @@ function assertThrowNoGLError(gl, 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,
|
||||
|
|
|
@ -40,37 +40,71 @@
|
|||
<script>
|
||||
"use strict";
|
||||
description("This test checks whether OffscreenCanvas webgl context honors the preserveDrawingBuffer flag.");
|
||||
const wtu = WebGLTestUtils;
|
||||
const pixels = new Uint8Array(4);
|
||||
|
||||
function getPixelsFromOffscreenWebgl(preserveFlag) {
|
||||
var canvas = document.createElement("canvas");
|
||||
var offscreenCanvas = transferredOffscreenCanvasCreation(canvas, 10, 10);
|
||||
var gl = offscreenCanvas.getContext("webgl", {preserveDrawingBuffer: preserveFlag});
|
||||
function checkPixels(color) {
|
||||
return (color[0] === pixels[0]) &&
|
||||
(color[1] === pixels[1]) &&
|
||||
(color[2] === pixels[2]) &&
|
||||
(color[3] === pixels[3]);
|
||||
}
|
||||
|
||||
// Draw some color on gl and commit
|
||||
const nextFrame = () => new Promise(r => requestAnimationFrame(r));
|
||||
|
||||
async function getPixelsFromOffscreenWebgl(preserveFlag, color, msg) {
|
||||
const canvas = document.createElement("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);
|
||||
gl.commit();
|
||||
|
||||
var pixels = new Uint8Array(4);
|
||||
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
|
||||
return pixels;
|
||||
let t;
|
||||
const t0 = await nextFrame();
|
||||
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
|
||||
if (t > t0 + 500) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (preserveFlag) {
|
||||
testPassed(msg);
|
||||
} else {
|
||||
testFailed(msg + '\nexpected: ' + color.toString() + ' was ' + pixels.toString());
|
||||
}
|
||||
}
|
||||
|
||||
if (!window.OffscreenCanvas) {
|
||||
testPassed("No OffscreenCanvas support");
|
||||
} else {
|
||||
// Test if OffscreenCanvas.webgl retains context if preserveDrawingBuffer is true.
|
||||
var pixelsPreserve = getPixelsFromOffscreenWebgl(true);
|
||||
shouldBe(pixelsPreserve, [255,0,255,255]);
|
||||
(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 context if presereDrawingbuffer is false.
|
||||
var pixelsNoPreserve = getPixelsFromOffscreenWebgl(false);
|
||||
shouldBe(pixelsNoPreserve, [0,0,0,0]);
|
||||
}
|
||||
|
||||
var successfullyParsed = true;
|
||||
// Test if OffscreenCanvas.webgl loses contents if preserveDrawingBuffer is false.
|
||||
await getPixelsFromOffscreenWebgl(false, [0, 0, 0, 0], "should not be preserved");
|
||||
finishTest();
|
||||
}
|
||||
})();
|
||||
|
||||
</script>
|
||||
<script src="../../js/js-test-post.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Resizing Test for OffscreenCanvas</title>
|
||||
<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>
|
||||
|
@ -39,7 +39,7 @@
|
|||
<div id="console"></div>
|
||||
<script>
|
||||
"use strict";
|
||||
description("This test ensures that the OffscreenCanvas context returns the correct image size after resizing.");
|
||||
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);
|
||||
|
@ -102,6 +102,9 @@ function testResizeOnTransferredOffscreenCanvas() {
|
|||
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();
|
||||
|
|
|
@ -103,6 +103,7 @@ if (!gl) {
|
|||
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);
|
||||
|
|
|
@ -56,6 +56,7 @@ void main()
|
|||
</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>
|
||||
|
@ -220,43 +221,51 @@ function runTestIteration(format, type, packAlignment, width, height)
|
|||
|
||||
description('Verify readPixels() works fine with various PACK_ALIGNMENT values.');
|
||||
|
||||
shouldBeNonNull("gl = wtu.create3DContext('example')")
|
||||
shouldBeNonNull("program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['pos', 'colorIn'])");
|
||||
|
||||
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();
|
||||
|
||||
for (var i = 0; i < formats.length; ++i) {
|
||||
var format = formats[i];
|
||||
function runAllIterations() {
|
||||
shouldBeNonNull("program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['pos', 'colorIn'])");
|
||||
|
||||
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);
|
||||
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>
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
</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>
|
||||
|
@ -44,273 +45,290 @@
|
|||
description("Checks that ReadPixels works as expected.");
|
||||
|
||||
var wtu = WebGLTestUtils;
|
||||
var canvas = document.getElementById("example");
|
||||
var gl = wtu.create3DContext(canvas);
|
||||
var contextVersion = wtu.getDefault3DContextVersion();
|
||||
|
||||
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;
|
||||
var width = 2;
|
||||
var height = 2;
|
||||
var continueTestFunc = continueTestPart1;
|
||||
|
||||
gl.clearColor(1, 1, 1, 1);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
function runTest(canvas, antialias) {
|
||||
var gl = wtu.create3DContext(canvas, {antialias: antialias});
|
||||
var contextVersion = wtu.getDefault3DContextVersion();
|
||||
|
||||
// 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();
|
||||
}
|
||||
var width = 2;
|
||||
var height = 2;
|
||||
var continueTestFunc = 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.clearColor(1, 1, 1, 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() {
|
||||
var invalidFormat = [gl.DEPTH_COMPONENT, gl.DEPTH_STENCIL, desktopGL.R8, gl.RGBA4, gl.LUMINANCE, gl.LUMINANCE_ALPHA];
|
||||
if (contextVersion < 2) {
|
||||
// They are valid in WebGL 2 or higher
|
||||
invalidFormat = invalidFormat.concat([desktopGL.RED, desktopGL.RG_INTEGER, desktopGL.RGBA_INTEGER]);
|
||||
}
|
||||
|
||||
var invalidTypeInfo = [
|
||||
{type: desktopGL.UNSIGNED_INT_24_8, dest: new Uint32Array(4)}
|
||||
];
|
||||
if (contextVersion < 2) {
|
||||
// They are valid in WebGL 2 or Higher
|
||||
invalidTypeInfo = invalidTypeInfo.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 invalid format or type");
|
||||
for (var ff = 0; ff < invalidFormat.length; ++ff) {
|
||||
var format = invalidFormat[ff];
|
||||
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 (var tt = 0; tt < invalidTypeInfo.length; ++tt) {
|
||||
var info = invalidTypeInfo[tt];
|
||||
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));
|
||||
}
|
||||
|
||||
var combinations = [
|
||||
{
|
||||
format: gl.RGBA,
|
||||
type: gl.UNSIGNED_BYTE,
|
||||
dest: new Uint8Array(4),
|
||||
},
|
||||
{
|
||||
format: gl.RGB,
|
||||
type: gl.UNSIGNED_BYTE,
|
||||
dest: new Uint8Array(3),
|
||||
},
|
||||
{
|
||||
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),
|
||||
},
|
||||
{
|
||||
format: gl.ALPHA,
|
||||
type: gl.UNSIGNED_BYTE,
|
||||
dest: new Uint8Array(1),
|
||||
}
|
||||
];
|
||||
if (contextVersion > 1) {
|
||||
combinations = combinations.concat([
|
||||
{
|
||||
format: gl.RED,
|
||||
type: gl.UNSIGNED_BYTE,
|
||||
dest: new Uint8Array(1),
|
||||
},
|
||||
{
|
||||
format: gl.RGBA_INTEGER,
|
||||
type: gl.UNSIGNED_INT,
|
||||
dest: new Uint32Array(4),
|
||||
},
|
||||
{
|
||||
format: gl.RGBA_INTEGER,
|
||||
type: gl.INT,
|
||||
dest: new Int32Array(4),
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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,
|
||||
"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;
|
||||
// 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) {
|
||||
continueTestPart3();
|
||||
continueTestPart1();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
function continueTestAfterContextRestored() {
|
||||
window.gl = wtu.create3DContext(canvas);
|
||||
var func = continueTestFunc;
|
||||
window.continueTestFunc = function() { testFailed("should not be here"); };
|
||||
func();
|
||||
}
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
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);
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
var combinations = [
|
||||
{
|
||||
format: gl.RGBA,
|
||||
type: gl.UNSIGNED_BYTE,
|
||||
dest: new Uint8Array(4),
|
||||
},
|
||||
{
|
||||
format: gl.RGB,
|
||||
type: gl.UNSIGNED_BYTE,
|
||||
dest: new Uint8Array(3),
|
||||
},
|
||||
{
|
||||
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),
|
||||
},
|
||||
{
|
||||
format: gl.ALPHA,
|
||||
type: gl.UNSIGNED_BYTE,
|
||||
dest: new Uint8Array(1),
|
||||
}
|
||||
];
|
||||
if (contextVersion > 1) {
|
||||
combinations = combinations.concat([
|
||||
{
|
||||
format: gl.RED,
|
||||
type: gl.UNSIGNED_BYTE,
|
||||
dest: new Uint8Array(1),
|
||||
},
|
||||
{
|
||||
format: gl.RGBA_INTEGER,
|
||||
type: gl.UNSIGNED_INT,
|
||||
dest: new Uint32Array(4),
|
||||
},
|
||||
{
|
||||
format: gl.RGBA_INTEGER,
|
||||
type: gl.INT,
|
||||
dest: new Int32Array(4),
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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,
|
||||
"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();
|
||||
}
|
||||
}
|
||||
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("");
|
||||
finishTest();
|
||||
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");
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
--min-version 1.0.4 blending.html
|
||||
--min-version 1.0.4 canvas-alpha-bug.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.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
|
||||
|
@ -19,6 +22,7 @@ gl-scissor-test.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
|
||||
|
@ -26,6 +30,7 @@ point-size.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
|
||||
|
|
|
@ -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">
|
||||
<link rel="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);
|
||||
gl.blendColor(10, 1, 1, 1);
|
||||
|
||||
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("State queries don't clamp.");
|
||||
|
||||
const gl = wtu.create3DContext();
|
||||
gl.blendColor(1000, 1, 1, 1);
|
||||
const was = gl.getParameter(gl.BLEND_COLOR);
|
||||
expectArray(was, [1000, 1, 1, 1]);
|
||||
},
|
||||
() => {
|
||||
debug('');
|
||||
debug('Blending for RGBA8:');
|
||||
|
||||
const gl = CreateContext();
|
||||
fb = CreateValidFb(gl, [[gl.RGBA8, gl.RGBA, gl.UNSIGNED_BYTE]]);
|
||||
shouldBeNonNull('fb');
|
||||
|
||||
const was = gl.drawAndRead(gl.UNSIGNED_BYTE);
|
||||
expectArray(was, [1, 2, 3, 4]);
|
||||
|
||||
if (gl.getExtension('EXT_color_buffer_float') ||
|
||||
gl.getExtension('EXT_color_buffer_half_float'))
|
||||
{
|
||||
debug('Enable color_buffer_half_float 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();
|
||||
if (gl.blitFramebuffer) {
|
||||
if (!gl.getExtension('EXT_color_buffer_float')) {
|
||||
testPassed('Missing ext EXT_color_buffer_float is optional, skipping.');
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!gl.getExtension('EXT_color_buffer_half_float')) {
|
||||
testPassed('Missing ext EXT_color_buffer_half_float is optional, skipping.');
|
||||
return;
|
||||
}
|
||||
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]);
|
||||
const was = gl.drawAndRead(gl.FLOAT);
|
||||
expectArray(was, [10, 2, 3, 4]);
|
||||
},
|
||||
() => {
|
||||
debug('');
|
||||
debug('Blending for RGBA32F:');
|
||||
|
||||
const gl = CreateContext();
|
||||
if (gl.blitFramebuffer) {
|
||||
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]);
|
||||
const 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, [10, 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>
|
|
@ -0,0 +1,132 @@
|
|||
<!--
|
||||
|
||||
/*
|
||||
** Copyright (c) 2018 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
-->
|
||||
|
||||
<!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>
|
||||
<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>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
<div id="canvases"></div>
|
||||
<div id="console"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,112 @@
|
|||
<!--
|
||||
|
||||
/*
|
||||
** Copyright (c) 2018 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
-->
|
||||
|
||||
<!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>
|
||||
<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>
|
||||
</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>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,146 @@
|
|||
<!--
|
||||
|
||||
/*
|
||||
** Copyright (c) 2019 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link 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>
|
|
@ -139,7 +139,7 @@ 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 generate errors");
|
||||
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);
|
||||
|
|
|
@ -0,0 +1,204 @@
|
|||
<!--
|
||||
|
||||
/*
|
||||
** Copyright (c) 2016 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
-->
|
||||
|
||||
<!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>
|
|
@ -47,4 +47,5 @@ texture-transparent-pixels-initialized.html
|
|||
--min-version 1.0.2 mipmap-fbo.html
|
||||
--min-version 1.0.3 --max-version 1.9.9 texture-fakeblack.html
|
||||
--min-version 1.0.3 texture-draw-with-2d-and-cube.html
|
||||
--min-version 1.0.4 texture-video-transparent.html
|
||||
--min-version 1.0.4 texture-with-flip-y-and-premultiply-alpha.html
|
||||
|
|
|
@ -111,11 +111,9 @@ function runTest() {
|
|||
|
||||
finishTest();
|
||||
}
|
||||
|
||||
loadImageAndStart(runTest);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<body onload="loadImageAndStart(runTest)">
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<canvas id="canvas" width="40" height="40"></canvas>
|
||||
|
|
|
@ -58,6 +58,8 @@ if (!gl) {
|
|||
|
||||
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))");
|
||||
|
@ -65,6 +67,26 @@ if (!gl) {
|
|||
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);
|
||||
});
|
||||
}
|
||||
|
||||
var successfullyParsed = true;
|
||||
|
|
|
@ -136,6 +136,7 @@ function test() {
|
|||
debug("");
|
||||
debug("testing: " + info.type);
|
||||
video = document.createElement("video");
|
||||
video.muted = true;
|
||||
var canPlay = true;
|
||||
if (!video.canPlayType) {
|
||||
testFailed("video.canPlayType required method missing");
|
||||
|
|
|
@ -50,6 +50,21 @@ void main()
|
|||
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;
|
||||
|
@ -128,6 +143,51 @@ function init()
|
|||
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();
|
||||
|
|
|
@ -152,7 +152,7 @@ function runTest(videoElement)
|
|||
<canvas id="example" width="64" height="48"></canvas>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<video id="vid" style="display:none;">
|
||||
<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"' />
|
||||
|
|
|
@ -119,7 +119,7 @@ function runNextTest() {
|
|||
return;
|
||||
}
|
||||
}
|
||||
wtu.dispatchTask(runNextTest);
|
||||
wtu.dispatchPromise(runNextTest);
|
||||
}
|
||||
|
||||
function testFormatType(t, test) {
|
||||
|
|
|
@ -0,0 +1,160 @@
|
|||
<!--
|
||||
|
||||
/*
|
||||
** Copyright (c) 2018 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Upload texture from animating transparent WebM</title>
|
||||
<link rel="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 init()
|
||||
{
|
||||
description("Upload texture from animating transparent WebM");
|
||||
|
||||
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 type = 'video/webm; codecs="vp8"';
|
||||
if (!video.canPlayType) {
|
||||
testFailed("video.canPlayType required method missing");
|
||||
finishTest();
|
||||
return;
|
||||
}
|
||||
if (!video.canPlayType(type).replace(/no/, '')) {
|
||||
debug(info.type + " unsupported");
|
||||
finishTest();
|
||||
return;
|
||||
};
|
||||
wtu.startPlayingAndWaitForVideo(video, runTest);
|
||||
}
|
||||
|
||||
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 = 5;
|
||||
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 = "";
|
||||
wtu.checkCanvasRectColor(gl, 4, 4, 8, 24, green, tolerance,
|
||||
/* sameFn */ () => { leftIsGreen = true; }, /* differentFn */ m => {}, debug);
|
||||
wtu.checkCanvasRectColor(gl, 20, 4, 8, 24, red, tolerance,
|
||||
/* sameFn */ () => { rightIsRed = true; }, /* differentFn */ m => { greenRedError = m; }, 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 => {}, debug);
|
||||
wtu.checkCanvasRectColor(gl, 4, 4, 8, 24, red, tolerance,
|
||||
/* sameFn */ () => { leftIsRed = true; }, /* differentFn */ m => { redBlueError = m; }, debug);
|
||||
|
||||
if (leftIsGreen) {
|
||||
if (rightIsRed) {
|
||||
testPassed("left is green, right is transparent-blended-with-red")
|
||||
} else {
|
||||
testFailed("left is green, but: " + greenRedError);
|
||||
}
|
||||
} else if (rightIsBlue) {
|
||||
if (leftIsRed) {
|
||||
testPassed("right is blue, left is transparent-blended-with-red");
|
||||
} else {
|
||||
testFailed("right is blue, but: " + redBlueError);
|
||||
}
|
||||
} else {
|
||||
testFailed("neither left is green nor right is blue")
|
||||
}
|
||||
}
|
||||
</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.webm" type='video/webm; codecs="vp8"' />
|
||||
</video>
|
||||
</body>
|
||||
</html>
|
|
@ -89,23 +89,22 @@ function resolvable() {
|
|||
return promise;
|
||||
}
|
||||
|
||||
function fence() {
|
||||
const promise = resolvable();
|
||||
function wait() {
|
||||
return new Promise(res => {
|
||||
setTimeout(res, 0);
|
||||
});
|
||||
}
|
||||
|
||||
async function fence() {
|
||||
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;
|
||||
let status;
|
||||
do {
|
||||
await wait();
|
||||
status = gl.clientWaitSync(sync, 0, 0);
|
||||
} while (status != gl.ALREADY_SIGNALED && status != gl.CONDITION_SATISIFIED);
|
||||
gl.deleteSync(sync);
|
||||
}
|
||||
|
||||
function checkGetBufferSubData(err, data) {
|
||||
|
@ -131,6 +130,8 @@ function copyBufferUsingTransformFeedback(src, dst) {
|
|||
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
|
||||
|
@ -143,120 +144,126 @@ function copyBufferUsingTransformFeedback(src, dst) {
|
|||
gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
|
||||
}
|
||||
|
||||
Promise.resolve()
|
||||
.then(() => {
|
||||
debug("");
|
||||
debug("write-read");
|
||||
gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
|
||||
checkGetBufferSubData(gl.NO_ERROR, "srcData");
|
||||
})
|
||||
.then(() => {
|
||||
debug("");
|
||||
debug("fence-wait-write-read");
|
||||
return fence().then(() => {
|
||||
gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
|
||||
checkGetBufferSubData(gl.NO_ERROR, "srcData");
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
debug("");
|
||||
debug("write-read-fence-wait");
|
||||
gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
|
||||
checkGetBufferSubData(gl.NO_ERROR, "srcData");
|
||||
return fence();
|
||||
})
|
||||
.then(() => {
|
||||
debug("");
|
||||
debug("write-fence-fence-wait-read");
|
||||
gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
|
||||
fence();
|
||||
return fence().then(() => {
|
||||
checkGetBufferSubData(gl.NO_ERROR, "srcData");
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
debug("");
|
||||
debug("write-fence-wait-read");
|
||||
gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
|
||||
return fence().then(() => {
|
||||
checkGetBufferSubData(gl.NO_ERROR, "srcData");
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
debug("");
|
||||
debug("write-fence-wait-write-read");
|
||||
gl.copyBufferSubData(gl.ARRAY_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
|
||||
return fence().then(() => {
|
||||
gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
|
||||
checkGetBufferSubData(gl.NO_ERROR, "srcData");
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
debug("");
|
||||
debug("write-fence-write-wait-read");
|
||||
gl.copyBufferSubData(gl.ARRAY_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
|
||||
(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);
|
||||
return p.then(() => {
|
||||
checkGetBufferSubData(gl.NO_ERROR, "srcData");
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
debug("");
|
||||
debug("write-fence-transformfeedback-wait-read");
|
||||
gl.copyBufferSubData(gl.ARRAY_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);
|
||||
return p.then(() => {
|
||||
checkGetBufferSubData(gl.NO_ERROR, "srcData");
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
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);
|
||||
return fence().then(() => {
|
||||
gl.bindBuffer(gl.COPY_WRITE_BUFFER, readbackBuffer);
|
||||
checkGetBufferSubData(gl.NO_ERROR, "srcData");
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
debug("");
|
||||
debug("write-fence-wait-delete-read");
|
||||
gl.copyBufferSubData(gl.ARRAY_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
|
||||
return fence().then(() => {
|
||||
deleteReadbackBuffer();
|
||||
checkGetBufferSubData(gl.INVALID_OPERATION, "noData");
|
||||
recreateReadbackBuffer();
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
debug("");
|
||||
debug("write-fence-delete-wait-read");
|
||||
gl.copyBufferSubData(gl.ARRAY_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
|
||||
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();
|
||||
return p.then(() => {
|
||||
checkGetBufferSubData(gl.INVALID_OPERATION, "noData");
|
||||
recreateReadbackBuffer();
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
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-fence-delete-wait-read");
|
||||
gl.copyBufferSubData(gl.ARRAY_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
|
||||
debug("write-delete-recreate-fence-wait-read");
|
||||
gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, 8);
|
||||
deleteReadbackBuffer();
|
||||
return fence().then(() => {
|
||||
checkGetBufferSubData(gl.INVALID_OPERATION, "noData");
|
||||
recreateReadbackBuffer();
|
||||
});
|
||||
})
|
||||
.then(finishTest);
|
||||
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>
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
ext-color-buffer-float.html
|
||||
ext-disjoint-timer-query-webgl2.html
|
||||
--min-version 2.0.1 ext-float-blend.html
|
||||
promoted-extensions.html
|
||||
promoted-extensions-in-shaders.html
|
||||
--min-version 2.0.1 webgl_multiview.html
|
||||
--min-version 2.0.1 webgl_multiview_depth.html
|
||||
--min-version 2.0.1 webgl_multiview_draw_buffers.html
|
||||
--min-version 2.0.1 webgl_multiview_flat_varying.html
|
||||
--min-version 2.0.1 webgl_multiview_instanced_draw.html
|
||||
--min-version 2.0.1 webgl_multiview_non_multiview_shaders.html
|
||||
--min-version 2.0.1 webgl_multiview_single_view_operations.html
|
||||
--min-version 2.0.1 webgl_multiview_timer_query.html
|
||||
--min-version 2.0.1 webgl_multiview_transform_feedback.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
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
<!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(){
|
||||
const colorBufferFloat = gl.getExtension("EXT_color_buffer_float");
|
||||
if (!colorBufferFloat) {
|
||||
testPassed("EXT_color_buffer_float is allowed to be missing.");
|
||||
return;
|
||||
}
|
||||
|
||||
debug("");
|
||||
debug("Testing float32 blending without EXT_float_blend");
|
||||
testExtFloatBlend(gl.RGBA32F);
|
||||
testExtFloatBlendMRT();
|
||||
testExtFloatBlendNonFloat32Type();
|
||||
|
||||
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(gl.RGBA32F);
|
||||
testExtFloatBlendMRT();
|
||||
testExtFloatBlendNonFloat32Type();
|
||||
})();
|
||||
|
||||
debug("");
|
||||
var successfullyParsed = true;
|
||||
</script>
|
||||
<script src="../../js/js-test-post.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
<!--
|
||||
/*
|
||||
** Copyright (c) 2019 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
-->
|
|
@ -29,20 +29,20 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>WebGL WEBGL_multiview Conformance Tests</title>
|
||||
<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/webgl_multiview_util.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_multiview
|
||||
#ifdef GL_OVR_multiview2
|
||||
my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
|
||||
#else
|
||||
// Error expected
|
||||
#error no GL_OVR_multiview;
|
||||
#error no GL_OVR_multiview2;
|
||||
#endif
|
||||
}
|
||||
</script>
|
||||
|
@ -63,12 +63,12 @@ function runExtensionDisabledTest()
|
|||
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 WEBGL_multiview");
|
||||
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 WEBGL_multiview");
|
||||
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 WEBGL_multiview");
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Can't query FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR without enabling OVR_multiview2");
|
||||
}
|
||||
|
||||
function runQueryTest()
|
||||
|
@ -112,17 +112,17 @@ function runInvalidTextureTypeTest()
|
|||
debug("Testing invalid texture types");
|
||||
let tex2D = createTextureWithNearestFiltering(gl.TEXTURE_2D);
|
||||
gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, 128, 128);
|
||||
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex2D, 0, 0, 1);
|
||||
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.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, texCube, 0, 0, 1);
|
||||
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.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex3D, 0, 0, 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");
|
||||
}
|
||||
|
||||
|
@ -143,7 +143,7 @@ function runFramebufferQueryTest(allocateStorage)
|
|||
}
|
||||
|
||||
let setupAndQuery = function(colorTex, levelSet, baseViewIndexSet, numViewsSet) {
|
||||
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, 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');
|
||||
|
@ -168,7 +168,7 @@ function runFramebufferQueryTest(allocateStorage)
|
|||
}
|
||||
|
||||
let setupSecondAttachmentAndQueryStatus = function(colorTex2, baseViewIndex, numViews, expectedStatus, msg) {
|
||||
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, colorTex2, 0, baseViewIndex, numViews);
|
||||
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);
|
||||
|
@ -212,7 +212,7 @@ function runFramebufferQueryTest(allocateStorage)
|
|||
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.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, maxViews);
|
||||
ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, maxViews);
|
||||
setupSecondAttachmentAndQueryStatus(colorTex2, 0, maxViews - 1, ext.FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR, 'numViews mismatch');
|
||||
}
|
||||
|
||||
|
@ -231,18 +231,18 @@ function runInvalidViewsTest()
|
|||
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.framebufferTextureMultiviewWEBGL(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, maxViews + 1);
|
||||
ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, maxViews + 1);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Specified too many views");
|
||||
ext.framebufferTextureMultiviewWEBGL(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 0);
|
||||
ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 0);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Specified zero views");
|
||||
ext.framebufferTextureMultiviewWEBGL(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, -1, 2);
|
||||
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.framebufferTextureMultiviewWEBGL(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex2, 0, maxLayers - maxViews + 1, maxViews);
|
||||
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.framebufferTextureMultiviewWEBGL(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex2, 0, maxLayers - maxViews, maxViews);
|
||||
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");
|
||||
}
|
||||
|
||||
|
@ -257,8 +257,8 @@ function runDetachTest()
|
|||
let fb = gl.createFramebuffer();
|
||||
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb);
|
||||
let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
|
||||
ext.framebufferTextureMultiviewWEBGL(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, maxViews);
|
||||
ext.framebufferTextureMultiviewWEBGL(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, null, 0, maxLayers + 1, 0);
|
||||
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) {
|
||||
|
@ -267,7 +267,7 @@ function runDetachTest()
|
|||
testPassed('FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE was NONE after detach');
|
||||
}
|
||||
|
||||
ext.framebufferTextureMultiviewWEBGL(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, maxViews);
|
||||
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);
|
||||
|
@ -286,15 +286,15 @@ function runShaderCompileTest(extensionEnabled)
|
|||
var macroFragmentProgram = wtu.setupProgram(gl, [wtu.simpleVertexShaderESSL300, "macroFragmentShader"], undefined, undefined, true);
|
||||
if (extensionEnabled) {
|
||||
if (macroFragmentProgram) {
|
||||
testPassed("GL_OVR_multiview defined in shaders when extension is enabled");
|
||||
testPassed("GL_OVR_multiview2 defined in shaders when extension is enabled");
|
||||
} else {
|
||||
testFailed("GL_OVR_multiview not defined in shaders when extension is enabled");
|
||||
testFailed("GL_OVR_multiview2 not defined in shaders when extension is enabled");
|
||||
}
|
||||
} else {
|
||||
if (macroFragmentProgram) {
|
||||
testFailed("GL_OVR_multiview defined in shaders when extension is disabled");
|
||||
testFailed("GL_OVR_multiview2 defined in shaders when extension is disabled");
|
||||
} else {
|
||||
testPassed("GL_OVR_multiview not defined in shaders when extension disabled");
|
||||
testPassed("GL_OVR_multiview2 not defined in shaders when extension disabled");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -326,7 +326,7 @@ function runClearTest()
|
|||
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.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
|
||||
ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
|
||||
|
||||
gl.viewport(0, 0, width, height);
|
||||
|
||||
|
@ -367,7 +367,7 @@ function runFragmentShaderRenderTest()
|
|||
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.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
|
||||
ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
|
||||
|
||||
gl.viewport(0, 0, width, height);
|
||||
wtu.drawUnitQuad(gl);
|
||||
|
@ -407,7 +407,7 @@ function runVertexShaderRenderTest()
|
|||
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.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
|
||||
ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
|
||||
|
||||
gl.viewport(0, 0, width, height);
|
||||
wtu.drawUnitQuad(gl);
|
||||
|
@ -448,7 +448,7 @@ function runRealisticUseCaseRenderTest()
|
|||
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.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
|
||||
ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
|
||||
|
||||
gl.viewport(0, 0, width, height);
|
||||
|
||||
|
@ -480,12 +480,12 @@ function runUniqueObjectTest()
|
|||
{
|
||||
debug("");
|
||||
debug("Testing that getExtension() returns the same object each time");
|
||||
gl.getExtension("WEBGL_multiview").myProperty = 2;
|
||||
gl.getExtension("OVR_multiview2").myProperty = 2;
|
||||
webglHarnessCollectGarbage();
|
||||
shouldBe('gl.getExtension("WEBGL_multiview").myProperty', '2');
|
||||
shouldBe('gl.getExtension("OVR_multiview2").myProperty', '2');
|
||||
}
|
||||
|
||||
description("This test verifies the functionality of the WEBGL_multiview extension, if it is available.");
|
||||
description("This test verifies the functionality of the OVR_multiview2 extension, if it is available.");
|
||||
|
||||
debug("");
|
||||
|
||||
|
@ -500,11 +500,11 @@ if (!gl) {
|
|||
|
||||
debug("");
|
||||
|
||||
if (!gl.getExtension("WEBGL_multiview")) {
|
||||
testPassed("No WEBGL_multiview support -- this is legal");
|
||||
if (!gl.getExtension("OVR_multiview2")) {
|
||||
testPassed("No OVR_multiview2 support -- this is legal");
|
||||
} else {
|
||||
testPassed("Successfully enabled WEBGL_multiview extension");
|
||||
ext = gl.getExtension('WEBGL_multiview');
|
||||
testPassed("Successfully enabled OVR_multiview2 extension");
|
||||
ext = gl.getExtension('OVR_multiview2');
|
||||
|
||||
runShaderCompileTest(true);
|
||||
|
|
@ -29,20 +29,20 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>WebGL WEBGL_multiview Conformance Tests</title>
|
||||
<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/webgl_multiview_util.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_multiview
|
||||
#ifdef GL_OVR_multiview2
|
||||
my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
|
||||
#else
|
||||
// Error expected
|
||||
#error no GL_OVR_multiview;
|
||||
#error no GL_OVR_multiview2;
|
||||
#endif
|
||||
}
|
||||
</script>
|
||||
|
@ -81,11 +81,11 @@ function runDepthRenderTest()
|
|||
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.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 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.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, depthTex, 0, 0, views);
|
||||
ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, depthTex, 0, 0, views);
|
||||
|
||||
let expectedStatus = gl.FRAMEBUFFER_COMPLETE;
|
||||
let status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
|
||||
|
@ -127,7 +127,7 @@ function runDepthRenderTest()
|
|||
}
|
||||
}
|
||||
|
||||
description("This test verifies drawing to depth buffers with the WEBGL_multiview extension, if it is available.");
|
||||
description("This test verifies drawing to depth buffers with the OVR_multiview2 extension, if it is available.");
|
||||
|
||||
debug("");
|
||||
|
||||
|
@ -138,11 +138,11 @@ if (!gl) {
|
|||
|
||||
debug("");
|
||||
|
||||
if (!gl.getExtension("WEBGL_multiview")) {
|
||||
testPassed("No WEBGL_multiview support -- this is legal");
|
||||
if (!gl.getExtension("OVR_multiview2")) {
|
||||
testPassed("No OVR_multiview2 support -- this is legal");
|
||||
} else {
|
||||
testPassed("Successfully enabled WEBGL_multiview extension");
|
||||
ext = gl.getExtension('WEBGL_multiview');
|
||||
testPassed("Successfully enabled OVR_multiview2 extension");
|
||||
ext = gl.getExtension('OVR_multiview2');
|
||||
|
||||
wtu.setupUnitQuad(gl, 0, 1);
|
||||
|
|
@ -29,11 +29,11 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>WebGL WEBGL_multiview Conformance Tests</title>
|
||||
<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/webgl_multiview_util.js"></script>
|
||||
<script src="../../js/tests/ovr_multiview2_util.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
|
@ -62,7 +62,7 @@ function runDrawBuffersClearTest()
|
|||
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.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + texIndex, colorTex[texIndex], 0, 0, views);
|
||||
ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + texIndex, colorTex[texIndex], 0, 0, views);
|
||||
drawBuffers[texIndex] = gl.COLOR_ATTACHMENT0 + texIndex;
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ function runDrawBuffersRenderTest()
|
|||
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.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + texIndex, colorTex[texIndex], 0, 0, views);
|
||||
ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + texIndex, colorTex[texIndex], 0, 0, views);
|
||||
drawBuffers[texIndex] = gl.COLOR_ATTACHMENT0 + texIndex;
|
||||
}
|
||||
|
||||
|
@ -147,7 +147,7 @@ function runDrawBuffersRenderTest()
|
|||
}
|
||||
}
|
||||
|
||||
description("This test verifies the functionality of the WEBGL_multiview extension when used with multiple draw buffers, if it is available.");
|
||||
description("This test verifies the functionality of the OVR_multiview2 extension when used with multiple draw buffers, if it is available.");
|
||||
|
||||
debug("");
|
||||
|
||||
|
@ -156,11 +156,11 @@ if (!gl) {
|
|||
} else {
|
||||
testPassed("WebGL context exists");
|
||||
|
||||
if (!gl.getExtension("WEBGL_multiview")) {
|
||||
testPassed("No WEBGL_multiview support -- this is legal");
|
||||
if (!gl.getExtension("OVR_multiview2")) {
|
||||
testPassed("No OVR_multiview2 support -- this is legal");
|
||||
} else {
|
||||
testPassed("Successfully enabled WEBGL_multiview extension");
|
||||
ext = gl.getExtension('WEBGL_multiview');
|
||||
testPassed("Successfully enabled OVR_multiview2 extension");
|
||||
ext = gl.getExtension('OVR_multiview2');
|
||||
|
||||
runDrawBuffersClearTest();
|
||||
|
|
@ -29,11 +29,11 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>WebGL WEBGL_multiview Conformance Tests</title>
|
||||
<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/webgl_multiview_util.js"></script>
|
||||
<script src="../../js/tests/ovr_multiview2_util.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
|
@ -69,7 +69,7 @@ function runFlatVaryingTest()
|
|||
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.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
|
||||
ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
|
||||
|
||||
gl.viewport(0, 0, width, height);
|
||||
wtu.drawUnitQuad(gl);
|
||||
|
@ -84,7 +84,7 @@ function runFlatVaryingTest()
|
|||
}
|
||||
}
|
||||
|
||||
description("This test verifies that flat varyings work in multiview shaders using WEBGL_multiview extension, if it is available.");
|
||||
description("This test verifies that flat varyings work in multiview shaders using OVR_multiview2 extension, if it is available.");
|
||||
|
||||
debug("");
|
||||
|
||||
|
@ -93,11 +93,11 @@ if (!gl) {
|
|||
} else {
|
||||
testPassed("WebGL context exists");
|
||||
|
||||
if (!gl.getExtension("WEBGL_multiview")) {
|
||||
testPassed("No WEBGL_multiview support -- this is legal");
|
||||
if (!gl.getExtension("OVR_multiview2")) {
|
||||
testPassed("No OVR_multiview2 support -- this is legal");
|
||||
} else {
|
||||
testPassed("Successfully enabled WEBGL_multiview extension");
|
||||
ext = gl.getExtension('WEBGL_multiview');
|
||||
testPassed("Successfully enabled OVR_multiview2 extension");
|
||||
ext = gl.getExtension('OVR_multiview2');
|
||||
|
||||
wtu.setupUnitQuad(gl, 0, 1);
|
||||
|
|
@ -29,11 +29,11 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>WebGL WEBGL_multiview Conformance Tests</title>
|
||||
<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/webgl_multiview_util.js"></script>
|
||||
<script src="../../js/tests/ovr_multiview2_util.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
|
@ -70,7 +70,7 @@ function runInstancedDrawTest()
|
|||
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.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 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);
|
||||
|
@ -96,7 +96,7 @@ function runInstancedDrawTest()
|
|||
}
|
||||
}
|
||||
|
||||
description("This test verifies instanced draws together with the WEBGL_multiview extension, if it is available.");
|
||||
description("This test verifies instanced draws together with the OVR_multiview2 extension, if it is available.");
|
||||
|
||||
debug("");
|
||||
|
||||
|
@ -105,11 +105,11 @@ if (!gl) {
|
|||
} else {
|
||||
testPassed("WebGL context exists");
|
||||
|
||||
if (!gl.getExtension("WEBGL_multiview")) {
|
||||
testPassed("No WEBGL_multiview support -- this is legal");
|
||||
if (!gl.getExtension("OVR_multiview2")) {
|
||||
testPassed("No OVR_multiview2 support -- this is legal");
|
||||
} else {
|
||||
testPassed("Successfully enabled WEBGL_multiview extension");
|
||||
ext = gl.getExtension('WEBGL_multiview');
|
||||
testPassed("Successfully enabled OVR_multiview2 extension");
|
||||
ext = gl.getExtension('OVR_multiview2');
|
||||
|
||||
wtu.setupUnitQuad(gl, 0, 1);
|
||||
|
|
@ -29,11 +29,11 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>WebGL WEBGL_multiview Conformance Tests</title>
|
||||
<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/webgl_multiview_util.js"></script>
|
||||
<script src="../../js/tests/ovr_multiview2_util.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
|
@ -66,7 +66,7 @@ function runNonMultiviewShaderTest()
|
|||
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.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 1);
|
||||
ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 1);
|
||||
|
||||
gl.viewport(0, 0, width, height);
|
||||
|
||||
|
@ -79,12 +79,12 @@ function runNonMultiviewShaderTest()
|
|||
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.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 2);
|
||||
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 WEBGL_multiview extension, if it is available.");
|
||||
description("This test verifies that non-multiview shaders work correctly with OVR_multiview2 extension, if it is available.");
|
||||
|
||||
debug("");
|
||||
|
||||
|
@ -93,11 +93,11 @@ if (!gl) {
|
|||
} else {
|
||||
testPassed("WebGL context exists");
|
||||
|
||||
if (!gl.getExtension("WEBGL_multiview")) {
|
||||
testPassed("No WEBGL_multiview support -- this is legal");
|
||||
if (!gl.getExtension("OVR_multiview2")) {
|
||||
testPassed("No OVR_multiview2 support -- this is legal");
|
||||
} else {
|
||||
testPassed("Successfully enabled WEBGL_multiview extension");
|
||||
ext = gl.getExtension('WEBGL_multiview');
|
||||
testPassed("Successfully enabled OVR_multiview2 extension");
|
||||
ext = gl.getExtension('OVR_multiview2');
|
||||
|
||||
wtu.setupUnitQuad(gl, 0, 1);
|
||||
|
|
@ -29,11 +29,11 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>WebGL WEBGL_multiview Conformance Tests</title>
|
||||
<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/webgl_multiview_util.js"></script>
|
||||
<script src="../../js/tests/ovr_multiview2_util.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
|
@ -58,7 +58,7 @@ function runSingleViewReadTest()
|
|||
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.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 1);
|
||||
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);
|
||||
|
@ -73,7 +73,7 @@ function runSingleViewReadTest()
|
|||
gl.getError();
|
||||
|
||||
// Also test for the error case with two views
|
||||
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 2);
|
||||
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");
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ function runSingleViewBlitTest()
|
|||
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.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 1);
|
||||
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);
|
||||
|
@ -116,7 +116,7 @@ function runSingleViewBlitTest()
|
|||
|
||||
// Also test for the error case with two views
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
|
||||
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 2);
|
||||
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");
|
||||
|
@ -135,7 +135,7 @@ function runSingleViewCopyTexImage2DTest()
|
|||
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.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 1);
|
||||
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);
|
||||
|
@ -154,7 +154,7 @@ function runSingleViewCopyTexImage2DTest()
|
|||
|
||||
// Also test for the error case with two views
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
|
||||
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 2);
|
||||
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");
|
||||
|
@ -173,7 +173,7 @@ function runSingleViewCopyTexSubImage2DTest()
|
|||
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.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 1);
|
||||
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);
|
||||
|
@ -193,7 +193,7 @@ function runSingleViewCopyTexSubImage2DTest()
|
|||
|
||||
// Also test for the error case with two views
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
|
||||
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 2);
|
||||
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");
|
||||
|
@ -212,7 +212,7 @@ function runSingleViewCopyTexSubImage3DTest()
|
|||
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.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 1);
|
||||
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);
|
||||
|
@ -232,13 +232,13 @@ function runSingleViewCopyTexSubImage3DTest()
|
|||
|
||||
// Also test for the error case with two views
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
|
||||
ext.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 2);
|
||||
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 WEBGL_multiview extension, if it is available.");
|
||||
description("This test verifies that framebuffers with only one view can be read from with OVR_multiview2 extension, if it is available.");
|
||||
|
||||
debug("");
|
||||
|
||||
|
@ -247,11 +247,11 @@ if (!gl) {
|
|||
} else {
|
||||
testPassed("WebGL context exists");
|
||||
|
||||
if (!gl.getExtension("WEBGL_multiview")) {
|
||||
testPassed("No WEBGL_multiview support -- this is legal");
|
||||
if (!gl.getExtension("OVR_multiview2")) {
|
||||
testPassed("No OVR_multiview2 support -- this is legal");
|
||||
} else {
|
||||
testPassed("Successfully enabled WEBGL_multiview extension");
|
||||
ext = gl.getExtension('WEBGL_multiview');
|
||||
testPassed("Successfully enabled OVR_multiview2 extension");
|
||||
ext = gl.getExtension('OVR_multiview2');
|
||||
|
||||
runSingleViewReadTest();
|
||||
|
|
@ -29,11 +29,11 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>WebGL WEBGL_multiview Conformance Tests</title>
|
||||
<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/webgl_multiview_util.js"></script>
|
||||
<script src="../../js/tests/ovr_multiview2_util.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
|
@ -60,7 +60,7 @@ function runClearTest()
|
|||
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.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
|
||||
ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
|
||||
|
||||
gl.viewport(0, 0, width, height);
|
||||
|
||||
|
@ -108,7 +108,7 @@ function runFragmentShaderRenderTest()
|
|||
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.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
|
||||
ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
|
||||
|
||||
gl.viewport(0, 0, width, height);
|
||||
|
||||
|
@ -130,7 +130,7 @@ function runFragmentShaderRenderTest()
|
|||
}
|
||||
}
|
||||
|
||||
description("This test verifies the functionality of the WEBGL_multiview extension and its interaction with EXT_disjoint_timer_query_webgl2, if it is available.");
|
||||
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("");
|
||||
|
||||
|
@ -139,11 +139,11 @@ if (!gl) {
|
|||
} else {
|
||||
testPassed("WebGL context exists");
|
||||
|
||||
if (!gl.getExtension("WEBGL_multiview") || !gl.getExtension("EXT_disjoint_timer_query_webgl2")) {
|
||||
testPassed("No WEBGL_multiview support or no EXT_disjoint_timer_query_webgl2 support -- this is legal");
|
||||
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 WEBGL_multiview and EXT_disjoint_timer_query_webgl2 extensions");
|
||||
ext = gl.getExtension('WEBGL_multiview');
|
||||
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();
|
|
@ -29,11 +29,11 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>WebGL WEBGL_multiview Conformance Tests</title>
|
||||
<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/webgl_multiview_util.js"></script>
|
||||
<script src="../../js/tests/ovr_multiview2_util.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
|
@ -70,7 +70,7 @@ function runTransformFeedbackTest()
|
|||
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.framebufferTextureMultiviewWEBGL(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
|
||||
ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
|
||||
|
||||
let xfb = gl.createTransformFeedback();
|
||||
gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, xfb);
|
||||
|
@ -88,14 +88,14 @@ function runTransformFeedbackTest()
|
|||
|
||||
gl.pauseTransformFeedback();
|
||||
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 even if the transform feedback is paused");
|
||||
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 = [0, 0, 0, 0];
|
||||
wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' should be untouched');
|
||||
let expectedColor = getExpectedColor(viewIndex);
|
||||
wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' should be colored ' + expectedColor);
|
||||
}
|
||||
|
||||
gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
|
||||
|
@ -116,7 +116,7 @@ function runTransformFeedbackTest()
|
|||
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from ending transform feedback");
|
||||
}
|
||||
|
||||
description("This test verifies interaction between transform feedback and the WEBGL_multiview extension, if it is available.");
|
||||
description("This test verifies interaction between transform feedback and the OVR_multiview2 extension, if it is available.");
|
||||
|
||||
debug("");
|
||||
|
||||
|
@ -125,11 +125,11 @@ if (!gl) {
|
|||
} else {
|
||||
testPassed("WebGL context exists");
|
||||
|
||||
if (!gl.getExtension("WEBGL_multiview")) {
|
||||
testPassed("No WEBGL_multiview support -- this is legal");
|
||||
if (!gl.getExtension("OVR_multiview2")) {
|
||||
testPassed("No OVR_multiview2 support -- this is legal");
|
||||
} else {
|
||||
testPassed("Successfully enabled WEBGL_multiview extension");
|
||||
ext = gl.getExtension('WEBGL_multiview');
|
||||
testPassed("Successfully enabled OVR_multiview2 extension");
|
||||
ext = gl.getExtension('OVR_multiview2');
|
||||
|
||||
wtu.setupUnitQuad(gl, 0, 1);
|
||||
|
|
@ -35,7 +35,7 @@ instanced-arrays.html
|
|||
--min-version 2.0.1 multisampling-fragment-evaluation.html
|
||||
out-of-bounds-index-buffers-after-copying.html
|
||||
--min-version 2.0.1 read-draw-when-missing-image.html
|
||||
--min-version 2.0.1 rendering-sampling-feedback-loop.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
|
||||
|
|
|
@ -48,13 +48,17 @@ description("This test verifies the behavior of blitFramebuffer when resolving d
|
|||
debug("Regression test for <a href='http://crbug.com/699566'>http://crbug.com/699566</a>");
|
||||
|
||||
function runTest(testParams) {
|
||||
// Assume a square framebuffer. Doesn't need to match the size of the canvas, necessarily.
|
||||
let sz = 64;
|
||||
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);
|
||||
', internalformat = ' + testParams.internalformat +
|
||||
', multisampled = ' + testParams.multisampled);
|
||||
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.width = sz;
|
||||
|
@ -63,10 +67,13 @@ function runTest(testParams) {
|
|||
var gl = wtu.create3DContext(canvas, testParams.attribs, 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("At least one multisampled format is required to be supported");
|
||||
return;
|
||||
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.
|
||||
|
@ -122,10 +129,33 @@ var tests = [
|
|||
antialias: false,
|
||||
},
|
||||
internalformat: 'RGB8',
|
||||
clearColor: [ 0.0, 1.0, 0.0, 1.0 ],
|
||||
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: {
|
||||
|
|
|
@ -109,8 +109,15 @@ function init() {
|
|||
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();
|
||||
|
@ -126,19 +133,18 @@ function detect_depth_stencil_feedback_loop() {
|
|||
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.NO_ERROR, "The test sampls from a image. The same image is used as depth buffer. But depth mask is false.");
|
||||
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.NO_ERROR, "The test samples from a image. The same image is used as depth buffer. But depth test is not enabled during rendering.");
|
||||
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);
|
||||
|
@ -155,12 +161,12 @@ function detect_depth_stencil_feedback_loop() {
|
|||
|
||||
gl.stencilMask(0x0);
|
||||
wtu.clearAndDrawUnitQuad(gl);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "The test sampls from a image. The same image is used as stencil buffer. But stencil mask is zero.");
|
||||
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.NO_ERROR, "The test samples from a image. The same image is used as stencil buffer. But stencil test is not enabled during rendering.");
|
||||
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() {
|
||||
|
|
|
@ -358,8 +358,14 @@ function runDrawTests() {
|
|||
// 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([gl.COLOR_ATTACHMENT0]);
|
||||
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.drawBuffers([gl.COLOR_ATTACHMENT0]);
|
||||
wtu.drawUnitQuad(gl);
|
||||
|
||||
drawBuffersUtils.checkAttachmentsForColorFn(attachments, function(attachment, index) {
|
||||
|
@ -370,8 +376,14 @@ function runDrawTests() {
|
|||
// 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([gl.COLOR_ATTACHMENT0]);
|
||||
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) {
|
||||
|
|
|
@ -86,7 +86,6 @@ function testNonSquareFramebufferTextureWithChangingBaseLevel() {
|
|||
{
|
||||
var levelW = Math.floor(width / Math.pow(2, level));
|
||||
var levelH = Math.floor(height / Math.pow(2, level));
|
||||
gl.viewport(0, 0, levelW, levelH);
|
||||
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_BASE_LEVEL, level);
|
||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, level);
|
||||
|
@ -95,6 +94,7 @@ function testNonSquareFramebufferTextureWithChangingBaseLevel() {
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -108,7 +108,7 @@ if (!gl) {
|
|||
function check_type_match() {
|
||||
gl.useProgram(program0);
|
||||
rendering([gl.COLOR_ATTACHMENT0, gl.NONE], gl.NO_ERROR);
|
||||
rendering([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1], 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);
|
||||
|
|
|
@ -1,148 +0,0 @@
|
|||
<!--
|
||||
|
||||
/*
|
||||
** Copyright (c) 2016 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
-->
|
||||
|
||||
<!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="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 fbo;
|
||||
var program;
|
||||
var positionLoc;
|
||||
var texCoordLoc;
|
||||
|
||||
if (!gl) {
|
||||
testFailed("WebGL context does not exist");
|
||||
} else {
|
||||
testPassed("WebGL context exists");
|
||||
|
||||
init();
|
||||
|
||||
// The sampling texture is bound to COLOR_ATTACHMENT1 during resource allocation
|
||||
allocate_resource();
|
||||
|
||||
rendering_sampling_feedback_loop([gl.NONE, gl.COLOR_ATTACHMENT1], gl.INVALID_OPERATION);
|
||||
rendering_sampling_feedback_loop([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1], gl.INVALID_OPERATION);
|
||||
rendering_sampling_feedback_loop([gl.COLOR_ATTACHMENT0, gl.NONE], gl.NO_ERROR);
|
||||
}
|
||||
|
||||
function init() {
|
||||
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);
|
||||
}
|
||||
|
||||
function allocate_resource() {
|
||||
tex0 = gl.createTexture();
|
||||
tex1 = gl.createTexture();
|
||||
fbo = gl.createFramebuffer();
|
||||
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, gl.UNSIGNED_BYTE, gl.RGBA);
|
||||
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex1);
|
||||
var texLoc = gl.getUniformLocation(program, "tex");
|
||||
gl.uniform1i(texLoc, 0);
|
||||
|
||||
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 rendering_sampling_feedback_loop(draw_buffers, error) {
|
||||
gl.drawBuffers(draw_buffers);
|
||||
|
||||
// Make sure framebuffer is complete before feedback loop detection
|
||||
if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
|
||||
testFailed("Framebuffer incomplete.");
|
||||
return;
|
||||
}
|
||||
|
||||
wtu.clearAndDrawUnitQuad(gl);
|
||||
wtu.glErrorShouldBe(gl, error, "Rendering to a texture where it samples from should geneates INVALID_OPERATION. Otherwise, it should be NO_ERROR");
|
||||
}
|
||||
|
||||
gl.bindTexture(gl.TEXTURE_2D, null);
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
gl.deleteTexture(tex0);
|
||||
gl.deleteTexture(tex1);
|
||||
gl.deleteFramebuffer(fbo);
|
||||
|
||||
var successfullyParsed = true;
|
||||
</script>
|
||||
<script src="../../js/js-test-post.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,240 @@
|
|||
<!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) 2013 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
-->
|
|
@ -8,6 +8,7 @@ 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 integer-cubemap-texture-sampling.html
|
||||
--min-version 2.0.1 integer-cubemap-specification-order-bug.html
|
||||
|
|
|
@ -70,7 +70,7 @@ function checkFramebuffer(expected) {
|
|||
}
|
||||
|
||||
var testInternalformat = function () {
|
||||
var goodByteFormats = [
|
||||
var goodUnormFormats = [
|
||||
"RGB",
|
||||
"RGBA",
|
||||
"LUMINANCE_ALPHA",
|
||||
|
@ -81,7 +81,7 @@ var testInternalformat = function () {
|
|||
"RGB8",
|
||||
"RGBA8",
|
||||
];
|
||||
var goodByteFormatsWithUnmatchedComponentSizes = [
|
||||
var goodUnormFormatsWithUnmatchedComponentSizes = [
|
||||
"RGB565",
|
||||
"RGBA4",
|
||||
"RGB5_A1",
|
||||
|
@ -94,6 +94,7 @@ var testInternalformat = function () {
|
|||
var goodIntFormats = [
|
||||
"R32I",
|
||||
"RG32I",
|
||||
"RGB32I",
|
||||
"RGBA32I",
|
||||
];
|
||||
var goodIntFormatsWithUnmatchedComponentSizes = [
|
||||
|
@ -101,12 +102,15 @@ var testInternalformat = function () {
|
|||
"R16I",
|
||||
"RG8I",
|
||||
"RG16I",
|
||||
"RGB8I",
|
||||
"RGB16I",
|
||||
"RGBA8I",
|
||||
"RGBA16I",
|
||||
];
|
||||
var goodUnsignedIntFormats = [
|
||||
"R32UI",
|
||||
"RG32UI",
|
||||
"RGB32UI",
|
||||
"RGBA32UI",
|
||||
];
|
||||
var goodUnsignedIntFormatsWithUnmatchedComponentSizes = [
|
||||
|
@ -115,26 +119,33 @@ var testInternalformat = function () {
|
|||
"RG8UI",
|
||||
"RG16UI",
|
||||
"RGB10_A2UI",
|
||||
"RGB8UI",
|
||||
"RGB16UI",
|
||||
"RGBA8UI",
|
||||
"RGBA16UI",
|
||||
];
|
||||
var badByteFormats = [
|
||||
const snormFormats = [
|
||||
"R8_SNORM",
|
||||
"RG8_SNORM",
|
||||
"RGB8_SNORM",
|
||||
"RGBA8_SNORM",
|
||||
];
|
||||
var badIntFormats = [
|
||||
"RGB8I",
|
||||
"RGB16I",
|
||||
"RGB32I",
|
||||
const float16Formats = [
|
||||
"R16F",
|
||||
"RG16F",
|
||||
"RGB16F",
|
||||
"RGBA16F",
|
||||
];
|
||||
var badUnsingedIntFormats = [
|
||||
"RGB8UI",
|
||||
"RGB16UI",
|
||||
"RGB32UI",
|
||||
const float32Formats = [
|
||||
"R32F",
|
||||
"RG32F",
|
||||
"RGB32F",
|
||||
"RGBA32F",
|
||||
];
|
||||
var badDepthStencilFormats = [
|
||||
const float11Formats = [
|
||||
"R11F_G11F_B10F",
|
||||
];
|
||||
const depthAndOrStencilFormats = [
|
||||
"DEPTH_COMPONENT16",
|
||||
"DEPTH_COMPONENT24",
|
||||
"DEPTH_COMPONENT32F",
|
||||
|
@ -148,68 +159,97 @@ var testInternalformat = function () {
|
|||
var fbo = gl.createFramebuffer();
|
||||
var srcTexture = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, srcTexture);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, srcTexFormatsTypes.internalformat, 64, 64, 0, srcTexFormatsTypes.format, srcTexFormatsTypes.type, null);
|
||||
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 + enumToString(gl[internalformat]));
|
||||
wtu.glErrorShouldBe(gl, expected, msg + srcTexFormatsTypes.internalformat + '=>' + internalformat);
|
||||
|
||||
gl.deleteTexture(srcTexture);
|
||||
gl.deleteFramebuffer(fbo);
|
||||
}
|
||||
|
||||
goodByteFormats.forEach(function(internalformat) {
|
||||
var srcTexFormatsTypes = { internalformat: gl.RGBA, format: gl.RGBA, type: gl.UNSIGNED_BYTE };
|
||||
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: gl.RGBA8, format: gl.RGBA, type: gl.UNSIGNED_BYTE };
|
||||
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 ");
|
||||
});
|
||||
goodByteFormatsWithUnmatchedComponentSizes.forEach(function(internalformat) {
|
||||
var srcTexFormatsTypes = { internalformat: gl.RGBA8, format: gl.RGBA, type: gl.UNSIGNED_BYTE };
|
||||
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: gl.SRGB8_ALPHA8, format: gl.RGBA, type: gl.UNSIGNED_BYTE };
|
||||
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: gl.RGBA32I, format: gl.RGBA_INTEGER, type: gl.INT };
|
||||
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: gl.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: gl.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: gl.RGBA32UI, format: gl.RGBA_INTEGER, type: gl.UNSIGNED_INT };
|
||||
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 ");
|
||||
});
|
||||
|
||||
badByteFormats.forEach(function(internalformat) {
|
||||
var srcTexFormatsTypes = { internalformat: gl.RGBA8, format: gl.RGBA, type: gl.UNSIGNED_BYTE };
|
||||
testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, gl.INVALID_ENUM, "copyTexImage2D should fail for bad internalformat ");
|
||||
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 ");
|
||||
});
|
||||
badIntFormats.forEach(function(internalformat) {
|
||||
var srcTexFormatsTypes = { internalformat: gl.RGBA32I, format: gl.RGBA_INTEGER, type: gl.INT };
|
||||
testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, gl.INVALID_ENUM, "copyTexImage2D should fail for bad 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 ");
|
||||
});
|
||||
badUnsingedIntFormats.forEach(function(internalformat) {
|
||||
var srcTexFormatsTypes = { internalformat: gl.RGBA32UI, format: gl.RGBA_INTEGER, type: gl.UNSIGNED_INT };
|
||||
testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, gl.INVALID_ENUM, "copyTexImage2D should fail for bad internalformat ");
|
||||
|
||||
snormFormats.forEach(function(internalformat) {
|
||||
const srcTexFormatsTypes = { internalformat: "RGBA8", format: gl.RGBA, type: gl.UNSIGNED_BYTE };
|
||||
testFormat(internalformat, srcTexFormatsTypes, gl.COLOR_ATTACHMENT0, gl.INVALID_ENUM, "copyTexImage2D should fail for snorm internalformat ");
|
||||
});
|
||||
badDepthStencilFormats.forEach(function(internalformat) {
|
||||
var srcTexFormatsTypes = { internalformat: gl.DEPTH24_STENCIL8, format: gl.DEPTH_STENCIL, type: gl.UNSIGNED_INT_24_8};
|
||||
testFormat(internalformat, srcTexFormatsTypes, gl.DEPTH_STENCIL_ATTACHMENT, gl.INVALID_ENUM, "copyTexImage2D should fail for bad 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);
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
<!--
|
||||
|
||||
/*
|
||||
** Copyright (c) 2018 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
-->
|
||||
|
||||
<!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>
|
||||
|
|
@ -108,6 +108,10 @@ function createTextureCube(layers, maxLevel) {
|
|||
return texture;
|
||||
}
|
||||
|
||||
function makePermutedLayers(layers, permutation) {
|
||||
return permutation.map(i => layers[i]);
|
||||
}
|
||||
|
||||
function test() {
|
||||
var kMaxLevel = 4;
|
||||
var kBlack = 0x0000;
|
||||
|
@ -151,9 +155,6 @@ function test() {
|
|||
}
|
||||
|
||||
var regularTex = createTextureCube(regularLayers, kMaxLevel);
|
||||
var weirdTex = createTextureCube(weirdLayers, kMaxLevel);
|
||||
|
||||
// At this point both textures should be the same.
|
||||
|
||||
var sampleProgram = wtu.setupProgram(gl, ["vs", "fs"], ["a_position"]);
|
||||
var regularLocation = gl.getUniformLocation(sampleProgram, "texRegular");
|
||||
|
@ -161,22 +162,68 @@ function test() {
|
|||
|
||||
wtu.setupQuad(gl, gl.getAttribLocation(sampleProgram, "a_position"));
|
||||
|
||||
gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
||||
|
||||
gl.activeTexture(gl.TEXTURE0);
|
||||
gl.bindTexture(gl.TEXTURE_CUBE_MAP, regularTex);
|
||||
gl.activeTexture(gl.TEXTURE0 + 1);
|
||||
gl.bindTexture(gl.TEXTURE_CUBE_MAP, weirdTex);
|
||||
|
||||
gl.uniform1i(regularLocation, 0);
|
||||
gl.uniform1i(weirdLocation, 1);
|
||||
|
||||
wtu.drawUnitQuad(gl);
|
||||
function testcase(layers1, casename) {
|
||||
var tex1 = createTextureCube(layers1, kMaxLevel);
|
||||
|
||||
wtu.checkCanvasRect(gl, 96, 32, 1, 1, [255, 0, 0, 255], "should be green");
|
||||
wtu.checkCanvasRect(gl, 96, 96, 1, 1, [255, 0, 0, 255], "should be green");
|
||||
wtu.checkCanvasRect(gl, 32, 32, 1, 1, [0, 255, 0, 255], "should be red");
|
||||
wtu.checkCanvasRect(gl, 32, 96, 1, 1, [0, 255, 0, 255], "should be red");
|
||||
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();
|
||||
|
|
|
@ -134,6 +134,7 @@ function runNextVideo() {
|
|||
debug("");
|
||||
debug("testing: " + videoInfo.type);
|
||||
video = document.createElement("video");
|
||||
video.muted = true;
|
||||
var canPlay = true;
|
||||
if (!video.canPlayType) {
|
||||
testFailed("video.canPlayType required method missing");
|
||||
|
|
|
@ -123,13 +123,13 @@ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
|
|||
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], "should draw with [0, 0, 255, 255]");
|
||||
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], "should draw with [255, 0, 0, 255]");
|
||||
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.
|
||||
|
@ -190,9 +190,8 @@ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
|
|||
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);
|
||||
// https://github.com/KhronosGroup/WebGL/pull/2728
|
||||
//gl.generateMipmap(gl.TEXTURE_2D);
|
||||
//wtu.glErrorShouldBe(gl, gl.NO_ERROR, "generateMipmap should succeed for zero-size texture");
|
||||
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");
|
||||
|
@ -206,9 +205,8 @@ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
|
|||
}
|
||||
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);
|
||||
// https://github.com/KhronosGroup/WebGL/pull/2728
|
||||
//gl.generateMipmap(gl.TEXTURE_2D);
|
||||
//wtu.glErrorShouldBe(gl, gl.NO_ERROR, "generateMipmap should succeed for zero-size texture");
|
||||
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");
|
||||
|
@ -234,7 +232,7 @@ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
|
|||
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], "should draw with [255, 0, 0, 255]");
|
||||
wtu.checkCanvas(gl, [255, 0, 0, 255], "non-zero base level texStorage2D: should draw with [255, 0, 0, 255]");
|
||||
gl.deleteTexture(tex);
|
||||
|
||||
})();
|
||||
|
|
|
@ -40,22 +40,103 @@
|
|||
<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)");
|
||||
|
||||
let imageData = new ImageData(64, 64);
|
||||
let texture = gl.createTexture();
|
||||
// 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");
|
||||
}
|
||||
|
||||
gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, 7);
|
||||
gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA8, 4, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, imageData);
|
||||
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);
|
||||
|
||||
|
|
|
@ -1,8 +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
|
||||
--min-version 2.0.1 switching-objects.html
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
<!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.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
-->
|
|
@ -67,6 +67,7 @@ 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;
|
||||
|
@ -81,8 +82,11 @@ if (!gl) {
|
|||
runTFBufferBindingTest();
|
||||
runObjectTest();
|
||||
runGetBufferSubDataTest();
|
||||
runOneOutFeedbackTest();
|
||||
runTwoOutFeedbackTest();
|
||||
runUnboundDeleteTest();
|
||||
runBoundDeleteTest();
|
||||
runOneOutputFeedbackTest();
|
||||
// Must be the last test, since it's asynchronous and calls finishTest().
|
||||
runTwoOutputFeedbackTest();
|
||||
}
|
||||
|
||||
function runBindingTest() {
|
||||
|
@ -169,9 +173,9 @@ function runObjectTest() {
|
|||
tf = null;
|
||||
}
|
||||
|
||||
function runOneOutFeedbackTest() {
|
||||
function runOneOutputFeedbackTest() {
|
||||
debug("");
|
||||
debug("Testing transform feedback processing");
|
||||
debug("Testing one-output transform feedback");
|
||||
|
||||
// Build the input and output buffers
|
||||
var in_data = [
|
||||
|
@ -184,7 +188,7 @@ function runOneOutFeedbackTest() {
|
|||
gl.bindBuffer(gl.ARRAY_BUFFER, in_buffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(in_data), gl.STATIC_DRAW);
|
||||
|
||||
var out_add_buffer = gl.createBuffer();
|
||||
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);
|
||||
|
||||
|
@ -208,6 +212,13 @@ function runOneOutFeedbackTest() {
|
|||
gl.enable(gl.RASTERIZER_DISCARD);
|
||||
gl.beginTransformFeedback(gl.POINTS);
|
||||
|
||||
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();
|
||||
|
@ -224,13 +235,18 @@ function runOneOutFeedbackTest() {
|
|||
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 runTwoOutFeedbackTest() {
|
||||
function runTwoOutputFeedbackTest() {
|
||||
debug("");
|
||||
debug("Testing transform feedback processing");
|
||||
debug("Testing two-output transform feedback");
|
||||
|
||||
// Build the input and output buffers
|
||||
var in_data = [
|
||||
|
@ -243,7 +259,7 @@ function runTwoOutFeedbackTest() {
|
|||
gl.bindBuffer(gl.ARRAY_BUFFER, in_buffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(in_data), gl.STATIC_DRAW);
|
||||
|
||||
var out_add_buffer = gl.createBuffer();
|
||||
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);
|
||||
|
||||
|
@ -302,6 +318,12 @@ function runTwoOutFeedbackTest() {
|
|||
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;
|
||||
|
||||
|
@ -324,6 +346,87 @@ function runTwoOutFeedbackTest() {
|
|||
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) {
|
||||
|
@ -347,7 +450,7 @@ function runGetBufferSubDataTest() {
|
|||
gl.bindBuffer(gl.ARRAY_BUFFER, in_buffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(in_data), gl.STATIC_DRAW);
|
||||
|
||||
var out_add_buffer = gl.createBuffer();
|
||||
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);
|
||||
|
||||
|
@ -448,8 +551,8 @@ function runVaryingsTest() {
|
|||
debug("");
|
||||
debug("Testing transform feedback varyings");
|
||||
|
||||
// Create the transform feedback shader. This is explicitly run after runFeedbackTest,
|
||||
// as re-llinking the shader here will test browser caching.
|
||||
// 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"]);
|
||||
|
|
|
@ -65,73 +65,84 @@ function makeFragmentShader(samplerType, 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, colorRenderable: true, 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: true, 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: true, 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], };
|
||||
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, 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], };
|
||||
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
|
||||
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], };
|
||||
// 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];
|
||||
|
@ -143,62 +154,11 @@ const textureInternalFormatInfo = {};
|
|||
});
|
||||
}
|
||||
|
||||
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;
|
||||
});
|
||||
|
||||
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, },
|
||||
|
||||
// these sampler types should probably be tested separtely as they have
|
||||
// various texParameter requirements
|
||||
// { type: 'samplerCubeShadow', uvType: 'vec4(0)', target: gl.TEXTURE_, },
|
||||
// { type: 'sampler2DShadow', uvType: 'vec3(0)', target: gl.TEXTURE_, },
|
||||
// { type: 'sampler2DArrayShadow', uvType: 'vec4(0)', target: gl.TEXTURE_, },
|
||||
];
|
||||
|
||||
const signedIntSamplerTypes = [
|
||||
|
@ -215,6 +175,12 @@ const unsignedIntSamplerTypes = [
|
|||
{ 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..
|
||||
|
@ -268,7 +234,7 @@ function runTest() {
|
|||
targetInfo.textures = [];
|
||||
Object.keys(textureInternalFormatInfo).forEach(function(internalFormat) {
|
||||
internalFormat = parseInt(internalFormat);
|
||||
const isDepthFormat = depthTextureFormats.indexOf(internalFormat) >= 0;
|
||||
const isDepthFormat = textureInternalFormatInfo[internalFormat].depth;
|
||||
if (target === gl.TEXTURE_3D && isDepthFormat) {
|
||||
return;
|
||||
}
|
||||
|
@ -289,12 +255,33 @@ function runTest() {
|
|||
});
|
||||
});
|
||||
|
||||
testSamplerTypes(floatSamplerTypes, floatTextureFormats);
|
||||
testSamplerTypes(signedIntSamplerTypes, intTextureFormats);
|
||||
testSamplerTypes(unsignedIntSamplerTypes, unsignedIntTextureFormats);
|
||||
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);
|
||||
|
||||
function testSamplerTypes(samplerTypes, compatibleFormats) {
|
||||
samplerTypes.forEach(function(samplerInfo) {
|
||||
// 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) {
|
||||
|
@ -308,12 +295,47 @@ function runTest() {
|
|||
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);
|
||||
const expected = compatibleFormats.indexOf(internalFormat) < 0 ? gl.INVALID_OPERATION : gl.NONE;
|
||||
wtu.glErrorShouldBe(gl, expected, `from draw with ${desc}`);
|
||||
});
|
||||
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);
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
vertex-array-object.html
|
||||
--min-version 2.0.1 vertex-array-object-and-disabled-attributes.html
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
<!--
|
||||
|
||||
/*
|
||||
** Copyright (c) 2018 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
-->
|
||||
|
||||
<!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);
|
||||
|
||||
var singleProgram = wtu.setupProgram(gl, ['singlevshader', 'singlefshader']);
|
||||
var dualProgram = wtu.setupProgram(gl, ['dualvshader', 'dualfshader']);
|
||||
|
||||
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>
|
||||
|
|
@ -95,6 +95,9 @@ goog.scope(function() {
|
|||
// 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.");
|
||||
|
@ -118,13 +121,6 @@ goog.scope(function() {
|
|||
_skip("blit.rect.nearest_consistency_out_of_bounds_min_reverse_src_x");
|
||||
_skip("blit.rect.nearest_consistency_out_of_bounds_min_reverse_src_y");
|
||||
|
||||
_setReason("Tricky blit rects can result in imperfect copies on Mac Intel driver.");
|
||||
// crbug.com/658724
|
||||
// deqp/functional/gles3/framebufferblit/rect_03.html
|
||||
_skip("blit.rect.nearest_consistency_mag_reverse_src_dst_y");
|
||||
// deqp/functional/gles3/framebufferblit/rect_04.html
|
||||
_skip("blit.rect.nearest_consistency_min_reverse_src_dst_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");
|
||||
|
@ -210,6 +206,25 @@ goog.scope(function() {
|
|||
// 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)
|
||||
|
||||
/*
|
||||
|
|
|
@ -31,20 +31,24 @@ 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 = 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]);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
tcuTestCase.getFilter = () => tcuTestCase.getQueryVal('filter');
|
||||
|
||||
/**
|
||||
* Indicates the state of an iteration operation.
|
||||
|
@ -128,6 +132,9 @@ goog.scope(function() {
|
|||
*/
|
||||
tcuTestCase.Runner.prototype.terminate = function() {
|
||||
finishTest();
|
||||
if (!tcuTestCase.isQuietMode()) {
|
||||
console.log('finishTest() after (in ms):', performance.now());
|
||||
}
|
||||
};
|
||||
|
||||
tcuTestCase.runner = new tcuTestCase.Runner();
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
--min-version 2.0.1 builtinprecision/00_test_list.txt
|
||||
# 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
|
||||
|
|
|
@ -54,6 +54,19 @@ var gluShaderUtil = framework.opengl.gluShaderUtil;
|
|||
|
||||
/** @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;
|
||||
|
@ -344,8 +357,6 @@ es3fFboColorbufferTests.FboColorMultiTex2DCase.prototype.render = function(dst)
|
|||
for (var ndx = 0; ndx < 2; ndx++) {
|
||||
var format = gl.RGBA;
|
||||
var dataType = gl.UNSIGNED_BYTE;
|
||||
var texW = 128;
|
||||
var texH = 128;
|
||||
var tmpTex;
|
||||
var fbo = ndx ? fbo1 : fbo0;
|
||||
var viewport = ndx ? this.m_tex1Size : this.m_tex0Size;
|
||||
|
@ -486,8 +497,6 @@ es3fFboColorbufferTests.FboColorTexCubeCase.prototype.render = function(dst) {
|
|||
var face = order[ndx];
|
||||
var format = gl.RGBA;
|
||||
var dataType = gl.UNSIGNED_BYTE;
|
||||
var texW = 128;
|
||||
var texH = 128;
|
||||
var tmpTex;
|
||||
var fbo = fbos[face];
|
||||
var viewport = this.m_texSize;
|
||||
|
@ -612,8 +621,6 @@ es3fFboColorbufferTests.FboColorTex2DArrayCase.prototype.preCheck = function() {
|
|||
var layer = order[ndx];
|
||||
var format = gl.RGBA;
|
||||
var dataType = gl.UNSIGNED_BYTE;
|
||||
var texW = 128;
|
||||
var texH = 128;
|
||||
var fbo = fbos[layer];
|
||||
var viewport = this.m_texSize;
|
||||
var data = new tcuTexture.TextureLevel(gluTextureUtil.mapGLTransferFormat(format, dataType), texW, texH, 1);
|
||||
|
@ -737,8 +744,6 @@ es3fFboColorbufferTests.FboColorTex3DCase.prototype.preCheck = function() {
|
|||
var layer = order[ndx];
|
||||
var format = gl.RGBA;
|
||||
var dataType = gl.UNSIGNED_BYTE;
|
||||
var texW = 128;
|
||||
var texH = 128;
|
||||
var fbo = fbos[layer];
|
||||
var viewport = this.m_texSize;
|
||||
var data = new tcuTexture.TextureLevel(gluTextureUtil.mapGLTransferFormat(format, dataType), texW, texH, 1);
|
||||
|
@ -848,8 +853,6 @@ es3fFboColorbufferTests.FboBlendCase.prototype.preCheck = function() {
|
|||
// Fill framebuffer with grid pattern.
|
||||
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]);
|
||||
|
@ -943,7 +946,7 @@ es3fFboColorbufferTests.FboColorbufferTests.prototype.init = function() {
|
|||
|
||||
for (var ndx = 0; ndx < colorFormats.length; ndx++) {
|
||||
clearGroup.addChild(new es3fFboColorbufferTests.FboColorClearCase(
|
||||
es3fFboTestUtil.getFormatName(colorFormats[ndx]), "", colorFormats[ndx], 129, 117));
|
||||
es3fFboTestUtil.getFormatName(colorFormats[ndx]), "", colorFormats[ndx], texNpotSizeA[0], texNpotSizeA[1]));
|
||||
}
|
||||
|
||||
var numGroups = 6;
|
||||
|
@ -956,7 +959,7 @@ es3fFboColorbufferTests.FboColorbufferTests.prototype.init = function() {
|
|||
}
|
||||
for (var ndx = 0; ndx < colorFormats.length; ndx++) {
|
||||
tex2DGroup[ndx % numGroups].addChild(new es3fFboColorbufferTests.FboColorMultiTex2DCase(
|
||||
es3fFboTestUtil.getFormatName(colorFormats[ndx]), "", colorFormats[ndx], [129, 117], colorFormats[ndx], [99, 128]));
|
||||
es3fFboTestUtil.getFormatName(colorFormats[ndx]), "", colorFormats[ndx], texNpotSizeA, colorFormats[ndx], texNpotSizeB));
|
||||
}
|
||||
|
||||
// .texcube
|
||||
|
@ -967,7 +970,7 @@ es3fFboColorbufferTests.FboColorbufferTests.prototype.init = function() {
|
|||
}
|
||||
for (var ndx = 0; ndx < colorFormats.length; ndx++) {
|
||||
texCubeGroup[ndx % numGroups].addChild(new es3fFboColorbufferTests.FboColorTexCubeCase(
|
||||
es3fFboTestUtil.getFormatName(colorFormats[ndx]), "", colorFormats[ndx], [128, 128]));
|
||||
es3fFboTestUtil.getFormatName(colorFormats[ndx]), "", colorFormats[ndx], texPotSize));
|
||||
}
|
||||
|
||||
// .tex2darray
|
||||
|
@ -978,7 +981,7 @@ es3fFboColorbufferTests.FboColorbufferTests.prototype.init = function() {
|
|||
}
|
||||
for (var ndx = 0; ndx < colorFormats.length; ndx++) {
|
||||
tex2DArrayGroup[ndx % numGroups].addChild(new es3fFboColorbufferTests.FboColorTex2DArrayCase(
|
||||
es3fFboTestUtil.getFormatName(colorFormats[ndx]), "", colorFormats[ndx], [128, 128, 5]));
|
||||
es3fFboTestUtil.getFormatName(colorFormats[ndx]), "", colorFormats[ndx], texPotSize));
|
||||
}
|
||||
|
||||
// .tex3d
|
||||
|
@ -989,7 +992,7 @@ es3fFboColorbufferTests.FboColorbufferTests.prototype.init = function() {
|
|||
}
|
||||
for (var ndx = 0; ndx < colorFormats.length; ndx++) {
|
||||
tex3DGroup[ndx % numGroups].addChild(new es3fFboColorbufferTests.FboColorTex3DCase(
|
||||
es3fFboTestUtil.getFormatName(colorFormats[ndx]), "", colorFormats[ndx], [128, 128, 5]));
|
||||
es3fFboTestUtil.getFormatName(colorFormats[ndx]), "", colorFormats[ndx], texPotSize));
|
||||
}
|
||||
|
||||
// .blend
|
||||
|
@ -1008,7 +1011,7 @@ es3fFboColorbufferTests.FboColorbufferTests.prototype.init = function() {
|
|||
continue; // Blending is not supported.
|
||||
|
||||
blendGroup.addChild(new es3fFboColorbufferTests.FboBlendCase(fmtName + "_src_over", "", format,
|
||||
[127, 111], gl.FUNC_ADD, gl.FUNC_ADD, gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ZERO, gl.ONE));
|
||||
texNpotSizeA, gl.FUNC_ADD, gl.FUNC_ADD, gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ZERO, gl.ONE));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1018,6 +1021,11 @@ es3fFboColorbufferTests.FboColorbufferTests.prototype.init = function() {
|
|||
*/
|
||||
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());
|
||||
|
|
|
@ -100,12 +100,7 @@ es3fLifetimeTests.ScaleProgram.prototype.draw = function(vao, scale, tf, dst) {
|
|||
es3fLifetimeTests.ScaleProgram.prototype.setPos = function(buffer, vao) {
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
||||
gl.bindVertexArray(vao);
|
||||
if (buffer) {
|
||||
gl.vertexAttribPointer(this.m_posLoc, NUM_COMPONENTS, gl.FLOAT, false, 0, 0);
|
||||
} else {
|
||||
var name = gl.getVertexAttrib(this.m_posLoc, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING);
|
||||
gl.deleteBuffer(name);
|
||||
}
|
||||
gl.vertexAttribPointer(this.m_posLoc, NUM_COMPONENTS, gl.FLOAT, false, 0, 0);
|
||||
gl.bindVertexArray(null);
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
||||
};
|
||||
|
|
|
@ -306,13 +306,13 @@ goog.scope(function() {
|
|||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufElements);
|
||||
|
||||
bufferedLogToConsole('gl.INVALID_ENUM is generated if mode is not an accepted value.');
|
||||
gl.drawElements(-1, 1, gl.UNSIGNED_BYTE, vertices);
|
||||
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, 1, -1, vertices);
|
||||
gl.drawElements(gl.POINTS, 0, -1, vertices);
|
||||
this.expectError(gl.INVALID_ENUM);
|
||||
gl.drawElements(gl.POINTS, 1, gl.FLOAT, vertices);
|
||||
gl.drawElements(gl.POINTS, 0, gl.FLOAT, vertices);
|
||||
this.expectError(gl.INVALID_ENUM);
|
||||
|
||||
bufferedLogToConsole('gl.INVALID_VALUE is generated if count is negative.');
|
||||
|
@ -323,7 +323,7 @@ goog.scope(function() {
|
|||
fbo = gl.createFramebuffer();
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
|
||||
gl.checkFramebufferStatus(gl.FRAMEBUFFER);
|
||||
gl.drawElements(gl.POINTS, 1, gl.UNSIGNED_BYTE, vertices);
|
||||
gl.drawElements(gl.POINTS, 0, gl.UNSIGNED_BYTE, vertices);
|
||||
this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
gl.deleteFramebuffer(fbo);
|
||||
|
@ -345,13 +345,13 @@ goog.scope(function() {
|
|||
gl.beginTransformFeedback (gl.POINTS);
|
||||
this.expectError (gl.NO_ERROR);
|
||||
|
||||
gl.drawElements (gl.POINTS, 1, gl.UNSIGNED_BYTE, vertices);
|
||||
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, 1, gl.UNSIGNED_BYTE, vertices);
|
||||
gl.drawElements (gl.POINTS, 0, gl.UNSIGNED_BYTE, vertices);
|
||||
this.expectError (gl.NO_ERROR);
|
||||
|
||||
gl.endTransformFeedback ();
|
||||
|
@ -373,7 +373,7 @@ goog.scope(function() {
|
|||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufElements);
|
||||
|
||||
bufferedLogToConsole('gl.INVALID_OPERATION is generated if gl.useProgram(null) was set.');
|
||||
gl.drawElements(gl.POINTS, 1, gl.UNSIGNED_BYTE, vertices);
|
||||
gl.drawElements(gl.POINTS, 0, gl.UNSIGNED_BYTE, vertices);
|
||||
this.expectError(gl.INVALID_OPERATION);
|
||||
|
||||
gl.deleteBuffer(bufElements);
|
||||
|
@ -392,13 +392,13 @@ goog.scope(function() {
|
|||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufElements);
|
||||
|
||||
bufferedLogToConsole('gl.INVALID_ENUM is generated if mode is not an accepted value.');
|
||||
gl.drawElements(-1, 1, gl.UNSIGNED_BYTE, vertices);
|
||||
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, 1, -1, vertices);
|
||||
gl.drawElements(gl.TRIANGLES, 0, -1, vertices);
|
||||
this.expectError(gl.INVALID_ENUM);
|
||||
gl.drawElements(gl.TRIANGLES, 1, gl.FLOAT, vertices);
|
||||
gl.drawElements(gl.TRIANGLES, 0, gl.FLOAT, vertices);
|
||||
this.expectError(gl.INVALID_ENUM);
|
||||
|
||||
bufferedLogToConsole('gl.INVALID_VALUE is generated if count is negative.');
|
||||
|
@ -409,7 +409,7 @@ goog.scope(function() {
|
|||
fbo = gl.createFramebuffer();
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
|
||||
gl.checkFramebufferStatus(gl.FRAMEBUFFER);
|
||||
gl.drawElements(gl.TRIANGLES, 1, gl.UNSIGNED_BYTE, vertices);
|
||||
gl.drawElements(gl.TRIANGLES, 0, gl.UNSIGNED_BYTE, vertices);
|
||||
this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
gl.deleteFramebuffer(fbo);
|
||||
|
@ -431,13 +431,13 @@ goog.scope(function() {
|
|||
gl.beginTransformFeedback (gl.TRIANGLES);
|
||||
this.expectError (gl.NO_ERROR);
|
||||
|
||||
gl.drawElements (gl.TRIANGLES, 1, gl.UNSIGNED_BYTE, vertices);
|
||||
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, 1, gl.UNSIGNED_BYTE, vertices);
|
||||
gl.drawElements (gl.TRIANGLES, 0, gl.UNSIGNED_BYTE, vertices);
|
||||
this.expectError (gl.NO_ERROR);
|
||||
|
||||
gl.endTransformFeedback ();
|
||||
|
@ -553,26 +553,26 @@ goog.scope(function() {
|
|||
this.expectError(gl.NO_ERROR);
|
||||
|
||||
bufferedLogToConsole('gl.INVALID_ENUM is generated if mode is not an accepted value.');
|
||||
gl.drawElementsInstanced(-1, 1, gl.UNSIGNED_BYTE, vertices, 1);
|
||||
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, 1, -1, vertices, 1);
|
||||
gl.drawElementsInstanced(gl.POINTS, 0, -1, vertices, 1);
|
||||
this.expectError(gl.INVALID_ENUM);
|
||||
gl.drawElementsInstanced(gl.POINTS, 1, gl.FLOAT, vertices, 1);
|
||||
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, 1);
|
||||
gl.drawElementsInstanced(gl.POINTS, -1, gl.UNSIGNED_BYTE, vertices, 0);
|
||||
this.expectError(gl.INVALID_VALUE);
|
||||
gl.drawElementsInstanced(gl.POINTS, 11, gl.UNSIGNED_BYTE, vertices, -1);
|
||||
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, 1, gl.UNSIGNED_BYTE, vertices, 1);
|
||||
gl.drawElementsInstanced(gl.POINTS, 0, gl.UNSIGNED_BYTE, vertices, 1);
|
||||
this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
gl.deleteFramebuffer(fbo);
|
||||
|
@ -594,13 +594,13 @@ goog.scope(function() {
|
|||
gl.beginTransformFeedback (gl.POINTS);
|
||||
this.expectError (gl.NO_ERROR);
|
||||
|
||||
gl.drawElementsInstanced (gl.POINTS, 1, gl.UNSIGNED_BYTE, vertices, 1);
|
||||
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, 1, gl.UNSIGNED_BYTE, vertices, 1);
|
||||
gl.drawElementsInstanced (gl.POINTS, 0, gl.UNSIGNED_BYTE, vertices, 1);
|
||||
this.expectError (gl.NO_ERROR);
|
||||
|
||||
gl.endTransformFeedback ();
|
||||
|
@ -626,7 +626,7 @@ goog.scope(function() {
|
|||
this.expectError(gl.NO_ERROR);
|
||||
|
||||
bufferedLogToConsole('gl.INVALID_OPERATION is generated if gl.useProgram(null) is set.');
|
||||
gl.drawElementsInstanced(gl.POINTS, 1, gl.UNSIGNED_BYTE, vertices, 1);
|
||||
gl.drawElementsInstanced(gl.POINTS, 0, gl.UNSIGNED_BYTE, vertices, 1);
|
||||
this.expectError(gl.INVALID_OPERATION);
|
||||
|
||||
gl.deleteBuffer(bufElements);
|
||||
|
@ -649,26 +649,26 @@ goog.scope(function() {
|
|||
this.expectError(gl.NO_ERROR);
|
||||
|
||||
bufferedLogToConsole('gl.INVALID_ENUM is generated if mode is not an accepted value.');
|
||||
gl.drawElementsInstanced(-1, 1, gl.UNSIGNED_BYTE, vertices, 1);
|
||||
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, 1, -1, vertices, 1);
|
||||
gl.drawElementsInstanced(gl.TRIANGLES, 0, -1, vertices, 1);
|
||||
this.expectError(gl.INVALID_ENUM);
|
||||
gl.drawElementsInstanced(gl.TRIANGLES, 1, gl.FLOAT, vertices, 1);
|
||||
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, 1);
|
||||
gl.drawElementsInstanced(gl.TRIANGLES, -1, gl.UNSIGNED_BYTE, vertices, 0);
|
||||
this.expectError(gl.INVALID_VALUE);
|
||||
gl.drawElementsInstanced(gl.TRIANGLES, 11, gl.UNSIGNED_BYTE, vertices, -1);
|
||||
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, 1, gl.UNSIGNED_BYTE, vertices, 1);
|
||||
gl.drawElementsInstanced(gl.TRIANGLES, 0, gl.UNSIGNED_BYTE, vertices, 1);
|
||||
this.expectError(gl.INVALID_FRAMEBUFFER_OPERATION);
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
gl.deleteFramebuffer(fbo);
|
||||
|
@ -690,13 +690,13 @@ goog.scope(function() {
|
|||
gl.beginTransformFeedback (gl.TRIANGLES);
|
||||
this.expectError (gl.NO_ERROR);
|
||||
|
||||
gl.drawElementsInstanced (gl.TRIANGLES, 1, gl.UNSIGNED_BYTE, vertices, 1);
|
||||
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, 1, gl.UNSIGNED_BYTE, vertices, 1);
|
||||
gl.drawElementsInstanced (gl.TRIANGLES, 0, gl.UNSIGNED_BYTE, vertices, 1);
|
||||
this.expectError (gl.NO_ERROR);
|
||||
|
||||
gl.endTransformFeedback ();
|
||||
|
@ -723,13 +723,13 @@ goog.scope(function() {
|
|||
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, 1, gl.UNSIGNED_BYTE, vertices);
|
||||
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, 1, -1, vertices);
|
||||
gl.drawRangeElements(gl.POINTS, 0, 1, 0, -1, vertices);
|
||||
this.expectError(gl.INVALID_ENUM);
|
||||
gl.drawRangeElements(gl.POINTS, 0, 1, 1, gl.FLOAT, vertices);
|
||||
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.');
|
||||
|
@ -737,14 +737,14 @@ goog.scope(function() {
|
|||
this.expectError(gl.INVALID_VALUE);
|
||||
|
||||
bufferedLogToConsole('gl.INVALID_VALUE is generated if end < start.');
|
||||
gl.drawRangeElements(gl.POINTS, 1, 0, 1, gl.UNSIGNED_BYTE, vertices);
|
||||
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, 1, gl.UNSIGNED_BYTE, vertices);
|
||||
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);
|
||||
|
@ -766,13 +766,13 @@ goog.scope(function() {
|
|||
gl.beginTransformFeedback (gl.POINTS);
|
||||
this.expectError (gl.NO_ERROR);
|
||||
|
||||
gl.drawRangeElements (gl.POINTS, 0, 1, 1, gl.UNSIGNED_BYTE, vertices);
|
||||
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, 1, gl.UNSIGNED_BYTE, vertices);
|
||||
gl.drawRangeElements (gl.POINTS, 0, 1, 0, gl.UNSIGNED_BYTE, vertices);
|
||||
this.expectError (gl.NO_ERROR);
|
||||
|
||||
gl.endTransformFeedback ();
|
||||
|
@ -796,7 +796,7 @@ goog.scope(function() {
|
|||
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, 1, gl.UNSIGNED_BYTE, vertices);
|
||||
gl.drawRangeElements(gl.POINTS, 0, 1, 0, gl.UNSIGNED_BYTE, vertices);
|
||||
this.expectError(gl.INVALID_OPERATION);
|
||||
|
||||
gl.deleteBuffer(bufElements);
|
||||
|
@ -816,13 +816,13 @@ goog.scope(function() {
|
|||
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, 1, gl.UNSIGNED_BYTE, vertices);
|
||||
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, 1, -1, vertices);
|
||||
gl.drawRangeElements(gl.TRIANGLES, 0, 1, 0, -1, vertices);
|
||||
this.expectError(gl.INVALID_ENUM);
|
||||
gl.drawRangeElements(gl.TRIANGLES, 0, 1, 1, gl.FLOAT, vertices);
|
||||
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.');
|
||||
|
@ -830,14 +830,14 @@ goog.scope(function() {
|
|||
this.expectError(gl.INVALID_VALUE);
|
||||
|
||||
bufferedLogToConsole('gl.INVALID_VALUE is generated if end < start.');
|
||||
gl.drawRangeElements(gl.TRIANGLES, 1, 0, 1, gl.UNSIGNED_BYTE, vertices);
|
||||
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, 1, gl.UNSIGNED_BYTE, vertices);
|
||||
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);
|
||||
|
@ -859,13 +859,13 @@ goog.scope(function() {
|
|||
gl.beginTransformFeedback (gl.TRIANGLES);
|
||||
this.expectError (gl.NO_ERROR);
|
||||
|
||||
gl.drawRangeElements (gl.TRIANGLES, 0, 1, 1, gl.UNSIGNED_BYTE, vertices);
|
||||
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, 1, gl.UNSIGNED_BYTE, vertices);
|
||||
gl.drawRangeElements (gl.TRIANGLES, 0, 1, 0, gl.UNSIGNED_BYTE, vertices);
|
||||
this.expectError (gl.NO_ERROR);
|
||||
|
||||
gl.endTransformFeedback ();
|
||||
|
|
|
@ -38,6 +38,11 @@ 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++)
|
||||
|
@ -2653,6 +2658,7 @@ es3fShaderOperatorTests.ShaderOperatorTests.prototype.init = function() {
|
|||
|
||||
// 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),
|
||||
|
@ -2663,6 +2669,10 @@ es3fShaderOperatorTests.ShaderOperatorTests.prototype.init = function() {
|
|||
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),
|
||||
|
@ -2673,6 +2683,10 @@ es3fShaderOperatorTests.ShaderOperatorTests.prototype.init = function() {
|
|||
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),
|
||||
|
@ -2686,6 +2700,10 @@ es3fShaderOperatorTests.ShaderOperatorTests.prototype.init = function() {
|
|||
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)));
|
||||
|
@ -2699,6 +2717,10 @@ es3fShaderOperatorTests.ShaderOperatorTests.prototype.init = function() {
|
|||
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)));
|
||||
|
@ -2712,6 +2734,10 @@ es3fShaderOperatorTests.ShaderOperatorTests.prototype.init = function() {
|
|||
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)));
|
||||
|
@ -2725,6 +2751,10 @@ es3fShaderOperatorTests.ShaderOperatorTests.prototype.init = function() {
|
|||
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),
|
||||
|
@ -2734,8 +2764,6 @@ es3fShaderOperatorTests.ShaderOperatorTests.prototype.init = function() {
|
|||
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)));
|
||||
|
||||
funcInfoGroups.push(comm);
|
||||
|
||||
// 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),
|
||||
|
@ -3196,6 +3224,11 @@ es3fShaderOperatorTests.ShaderOperatorTests.prototype.init = function() {
|
|||
*/
|
||||
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());
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче