mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 16:22:00 +00:00
Bug 1724535 - Update WebGL CTS checkout. r=lsalzman
Differential Revision: https://phabricator.services.mozilla.com/D122657
This commit is contained in:
parent
0d54d4b040
commit
360dba0b1c
@ -1 +1 @@
|
||||
master
|
||||
main
|
||||
|
@ -52,12 +52,7 @@ There is supposed to be an example drawing here, but it's not important.
|
||||
componentSize: 4,
|
||||
normalize: false,
|
||||
},
|
||||
{ data: new Float32Array([ 0, 1, 0, 1, 0, 0, 0, 0, 0 ]),
|
||||
type: gl.FLOAT,
|
||||
componentSize: 4,
|
||||
normalize: false,
|
||||
},
|
||||
{ data: new Uint16Array([ 0, 32767, 0, 32767, 0, 0, 0, 0, 0 ]),
|
||||
{ data: new Uint16Array([ 0, 32767, 0, 32767, 0, 0, 0, 0, 0]),
|
||||
type: gl.SHORT,
|
||||
componentSize: 2,
|
||||
normalize: true,
|
||||
@ -99,6 +94,41 @@ There is supposed to be an example drawing here, but it's not important.
|
||||
}
|
||||
];
|
||||
|
||||
if (wtu.getDefault3DContextVersion() >= 2) {
|
||||
tests.push(...[
|
||||
{ data: new Int32Array([ 0, 1, 0, 1, 0, 0, 0, 0, 0]),
|
||||
type: gl.INT,
|
||||
componentSize: 4,
|
||||
normalize: false,
|
||||
},
|
||||
{ data: new Int32Array([ 0, 2147483647, 0, 2147483647, 0, 0, 0, 0, 0]),
|
||||
type: gl.INT,
|
||||
componentSize: 4,
|
||||
normalize: true,
|
||||
},
|
||||
{ data: new Uint32Array([ 0, 1, 0, 1, 0, 0, 0, 0, 0]),
|
||||
type: gl.UNSIGNED_INT,
|
||||
componentSize: 4,
|
||||
normalize: false,
|
||||
},
|
||||
{ data: new Uint32Array([ 0, 4294967295, 0, 4294967295, 0, 0, 0, 0, 0]),
|
||||
type: gl.UNSIGNED_INT,
|
||||
componentSize: 4,
|
||||
normalize: true,
|
||||
},
|
||||
{ data: new Uint16Array([ 0, 0b11110000000000, 0, 0b11110000000000, 0, 0, 0, 0, 0]),
|
||||
type: gl.HALF_FLOAT,
|
||||
componentSize: 2,
|
||||
normalize: false,
|
||||
},
|
||||
{ data: new Uint16Array([ 0, 0b11110000000000, 0, 0b11110000000000, 0, 0, 0, 0, 0]),
|
||||
type: gl.HALF_FLOAT,
|
||||
componentSize: 2,
|
||||
normalize: false,
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
var vertexObject = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, 1024, gl.STATIC_DRAW);
|
||||
|
@ -67,10 +67,10 @@ if (!gl) {
|
||||
gl.vertexAttribPointer(0, 1, gl.UNSIGNED_INT, 0, 0, 0);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM,
|
||||
"vertexAttribPointer should not support UNSIGNED_INT");
|
||||
gl.vertexAttribPointer(0, 1, gl.FIXED, 0, 0, 0);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM,
|
||||
"vertexAttribPointer should not support FIXED");
|
||||
}
|
||||
gl.vertexAttribPointer(0, 1, gl.FIXED, 0, 0, 0);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM,
|
||||
"vertexAttribPointer should not support FIXED");
|
||||
|
||||
var checkVertexAttribPointer = function(
|
||||
gl, err, reason, size, type, normalize, stride, offset) {
|
||||
@ -100,6 +100,16 @@ if (!gl) {
|
||||
{ type:gl.FLOAT, bytesPerComponent: 4 },
|
||||
];
|
||||
|
||||
if (wtu.getDefault3DContextVersion() >= 2) {
|
||||
types.push(...[
|
||||
{ type:gl.INT, bytesPerComponent: 4 },
|
||||
{ type:gl.UNSIGNED_INT, bytesPerComponent: 4 },
|
||||
{ type:gl.HALF_FLOAT, bytesPerComponent: 2 },
|
||||
{ type:gl.INT_2_10_10_10_REV, bytesPerComponent: 4, minSize: 4 },
|
||||
{ type:gl.UNSIGNED_INT_2_10_10_10_REV, bytesPerComponent: 4, minSize: 4 },
|
||||
]);
|
||||
}
|
||||
|
||||
for (var ii = 0; ii < types.length; ++ii) {
|
||||
var info = types[ii];
|
||||
debug("");
|
||||
@ -128,6 +138,10 @@ if (!gl) {
|
||||
reason = "because stride is bad";
|
||||
err = gl.INVALID_OPERATION;
|
||||
}
|
||||
if (size < info.minSize) {
|
||||
reason = "because size < minSize";
|
||||
err = gl.INVALID_OPERATION;
|
||||
}
|
||||
checkVertexAttribPointer(
|
||||
gl, err, reason, size, info.type, false, stride, offset);
|
||||
}
|
||||
@ -135,10 +149,10 @@ if (!gl) {
|
||||
|
||||
if (offset == 0) {
|
||||
checkVertexAttribPointer(
|
||||
gl, gl.NO_ERROR, "at stride limit",
|
||||
gl, size < info.minSize ? gl.INVALID_OPERATION : gl.NO_ERROR, "at stride limit",
|
||||
size, info.type, false, stride, offset);
|
||||
checkVertexAttribPointer(
|
||||
gl, gl.INVALID_VALUE, "over stride limit",
|
||||
gl, size < info.minSize ? [gl.INVALID_OPERATION, gl.INVALID_VALUE] : gl.INVALID_VALUE, "over stride limit",
|
||||
size, info.type, false,
|
||||
stride + info.bytesPerComponent, offset);
|
||||
}
|
||||
|
@ -94,15 +94,24 @@ function bufferDataSizesTest() {
|
||||
|
||||
{ parameter: new ArrayBuffer(0), expectedBufferSize: 0 },
|
||||
{ parameter: new ArrayBuffer(4), expectedBufferSize: 4 },
|
||||
{ parameter: new Uint8Array(new ArrayBuffer(5)), expectedBufferSize: 5 },
|
||||
{ parameter: new DataView(new ArrayBuffer(7)), expectedBufferSize: 7 },
|
||||
|
||||
{ parameter: "WebGL Rocks!", expectedBufferSize: 0 },
|
||||
{ parameter: { mystring: "WebGL Rocks!" }, expectedBufferSize: 0 },
|
||||
];
|
||||
|
||||
if (window.SharedArrayBuffer) {
|
||||
bufferDataParams.push(
|
||||
{ parameter: new SharedArrayBuffer(3), expectedBufferSize: 3 },
|
||||
{ parameter: new Uint8Array(new SharedArrayBuffer(6)), expectedBufferSize: 6 },
|
||||
{ parameter: new DataView(new SharedArrayBuffer(8)), expectedBufferSize: 8 }
|
||||
);
|
||||
}
|
||||
|
||||
bufferDataParams.forEach(function (bufferDataParam) {
|
||||
var buffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
||||
|
||||
gl.bufferData(gl.ARRAY_BUFFER, bufferDataParam.parameter, gl.STATIC_DRAW);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Passing " + bufferDataParam.parameter + " to bufferData");
|
||||
|
||||
@ -154,6 +163,18 @@ function bufferSubDataTest() {
|
||||
shouldThrow("gl.bufferSubData(gl.ARRAY_BUFFER, 0, { mynumber: 42});");
|
||||
shouldThrow("gl.bufferSubData(gl.ARRAY_BUFFER, 10, null)");
|
||||
shouldThrow("gl.bufferSubData(gl.ARRAY_BUFFER, 10, undefined)");
|
||||
|
||||
if (window.SharedArrayBuffer) {
|
||||
const validDatas = [
|
||||
'new SharedArrayBuffer(3)',
|
||||
'new Uint8Array(new SharedArrayBuffer(3))',
|
||||
'new DataView(new SharedArrayBuffer(3))',
|
||||
];
|
||||
for (const x of validDatas) {
|
||||
shouldNotThrow(`gl.bufferSubData(gl.ARRAY_BUFFER, 0, ${x})`);
|
||||
}
|
||||
}
|
||||
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should generate no GL error");
|
||||
|
||||
// -
|
||||
|
@ -13,6 +13,7 @@ drawingbuffer-test.html
|
||||
--min-version 1.0.4 render-after-resize-test.html
|
||||
--min-version 1.0.2 texture-bindings-unaffected-on-resize.html
|
||||
--min-version 1.0.2 to-data-url-test.html
|
||||
--min-version 1.0.4 to-data-url-after-composite.html
|
||||
viewport-unchanged-upon-resize.html
|
||||
--min-version 1.0.4 webgl-to-2d-canvas.html
|
||||
|
||||
|
@ -36,10 +36,6 @@ const SMALL = 2;
|
||||
// different results. Sometimes wrong, sometimes correct.
|
||||
const LARGE = 1200;
|
||||
|
||||
function render() {
|
||||
|
||||
}
|
||||
|
||||
gl.uniform4fv(colorLocation, [0.0, 1.0, 0.0, 1.0]);
|
||||
|
||||
// -
|
||||
@ -64,6 +60,19 @@ wtu.drawUnitQuad(gl);
|
||||
|
||||
wtu.checkCanvasRect(gl, 0, 0, 1, 1, [ 0, 255, 0, 255 ]);
|
||||
|
||||
debug('\nCause a GL error, then resize and render.');
|
||||
gl.depthFunc(0); // Causes INVALID_ENUM
|
||||
gl.canvas.width = gl.canvas.height = LARGE;
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
gl.canvas.width = gl.canvas.height = SMALL;
|
||||
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
wtu.drawUnitQuad(gl);
|
||||
|
||||
wtu.checkCanvasRect(gl, 0, 0, 1, 1, [ 0, 255, 0, 255 ]);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR);
|
||||
|
||||
// -
|
||||
|
||||
debug('\nRender, no-op resize, then depth-fail render.');
|
||||
|
@ -0,0 +1,51 @@
|
||||
<!--
|
||||
Copyright (c) 2021 The Khronos Group Inc.
|
||||
Use of this source code is governed by an MIT-style license that can be
|
||||
found in the LICENSE.txt file.
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>WebGL toDataURL after composite test</title>
|
||||
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
|
||||
<script src="../../js/js-test-pre.js"></script>
|
||||
<script src="../../js/webgl-test-utils.js"> </script>
|
||||
</head>
|
||||
<body>
|
||||
<canvas width="20" height="20" style="border: 1px solid black; width: 128px; height: 128px" id="c3d"></canvas>
|
||||
<canvas width="20" height="20" style="border: 1px solid black; width: 128px; height: 128px" id="c2d"></canvas>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<script type="application/javascript">
|
||||
const wtu = WebGLTestUtils;
|
||||
let gl;
|
||||
let ctx;
|
||||
|
||||
function main() {
|
||||
description();
|
||||
const c2d = document.getElementById("c2d");
|
||||
ctx = c2d.getContext("2d");
|
||||
gl = wtu.create3DContext("c3d", { preserveDrawingBuffer: true });
|
||||
|
||||
// Clear to green
|
||||
gl.clearColor(0.0, 1.0, 0.0, 1.0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
wtu.waitForComposite(() => {
|
||||
// Performs gl.canvas.toDataURL() internally
|
||||
let img = wtu.makeImageFromCanvas(gl.canvas, function() {
|
||||
ctx.drawImage(img, 0, 0);
|
||||
wtu.checkCanvas(ctx, [0, 255, 0], "toDataURL loaded into image, drawn into 2D context, should be green", 5);
|
||||
finishTest();
|
||||
});
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
main();
|
||||
var successfullyParsed = true;
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -26,13 +26,34 @@ var ctx;
|
||||
var main = function() {
|
||||
description();
|
||||
ctx = document.getElementById("c2d").getContext("2d");
|
||||
gl = wtu.create3DContext("c3d");
|
||||
|
||||
if (!gl) {
|
||||
testFailed("can't create 3d context");
|
||||
finishTest();
|
||||
return;
|
||||
}
|
||||
var updateCanvas = function(width, height, attributes) {
|
||||
var canvas = document.getElementById("c3d");
|
||||
|
||||
if (gl && (gl.attributes !== attributes)) {
|
||||
// Attributes changed, recreate the canvas
|
||||
var newCanvas = canvas.cloneNode();
|
||||
canvas.parentNode.replaceChild(newCanvas, canvas);
|
||||
canvas = newCanvas;
|
||||
gl = undefined;
|
||||
}
|
||||
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
|
||||
if (!gl) {
|
||||
gl = wtu.create3DContext(canvas, attributes);
|
||||
|
||||
if (!gl) {
|
||||
testFailed("can't create 3d context");
|
||||
return;
|
||||
}
|
||||
|
||||
gl.attributes = attributes;
|
||||
}
|
||||
|
||||
return gl;
|
||||
};
|
||||
|
||||
var clearRect = function(gl, x, y, width, height, color) {
|
||||
gl.clearColor(color[0] / 255, color[1] / 255, color[2] / 255, color[3] / 255);
|
||||
@ -40,10 +61,18 @@ var main = function() {
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
};
|
||||
|
||||
var testSize = function(gl, width, height, callback) {
|
||||
debug("testing " + width + " by " + height);
|
||||
gl.canvas.width = width;
|
||||
gl.canvas.height = height;
|
||||
var testSize = function(width, height, attributes, callback) {
|
||||
let attributesDebugMessage = "";
|
||||
if (attributes) {
|
||||
attributesDebugMessage = " attributes: " + JSON.stringify(attributes);
|
||||
}
|
||||
debug("testing " + width + " by " + height + attributesDebugMessage);
|
||||
var gl = updateCanvas(width, height, attributes);
|
||||
if (!gl) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
gl.viewport(0, 0, width, height);
|
||||
gl.enable(gl.SCISSOR_TEST);
|
||||
|
||||
@ -71,6 +100,9 @@ var main = function() {
|
||||
});
|
||||
};
|
||||
|
||||
const premultipliedAlphaAttributes = {
|
||||
premultipliedAlpha: false,
|
||||
};
|
||||
var tests = [
|
||||
{ width: 16 , height: 16 , },
|
||||
{ width: 16 - 1, height: 16 , },
|
||||
@ -87,6 +119,7 @@ var main = function() {
|
||||
{ width: 512 - 1, height: 512 - 1, },
|
||||
{ width: 512 + 1, height: 512 - 1, },
|
||||
{ width: 512 - 1, height: 512 + 1, },
|
||||
{ width: 16 , height: 16 , attributes: premultipliedAlphaAttributes},
|
||||
];
|
||||
var testIndex = 0;
|
||||
var runNextTest = function() {
|
||||
@ -95,7 +128,7 @@ var main = function() {
|
||||
return;
|
||||
}
|
||||
var test = tests[testIndex++];
|
||||
testSize(gl, test.width, test.height, function() {
|
||||
testSize(test.width, test.height, test.attributes, function() {
|
||||
setTimeout(runNextTest, 0);
|
||||
})
|
||||
};
|
||||
|
@ -12,6 +12,7 @@ context-attributes-alpha-depth-stencil-antialias.html
|
||||
context-lost-restored.html
|
||||
context-lost.html
|
||||
--max-version 1.9.9 context-type-test.html
|
||||
--min-version 1.0.4 deleted-object-behavior.html
|
||||
incorrect-context-object-behaviour.html
|
||||
--max-version 1.9.9 methods.html
|
||||
premultiplyalpha-test.html
|
||||
|
@ -17,13 +17,13 @@ found in the LICENSE.txt file.
|
||||
display: inline-block;
|
||||
}
|
||||
canvas {
|
||||
width:50px;
|
||||
height:50px;
|
||||
width:10px;
|
||||
height:10px;
|
||||
}
|
||||
.square {
|
||||
display:inline-block;
|
||||
width:50px;
|
||||
height:50px;
|
||||
width:10px;
|
||||
height:10px;
|
||||
background-color:red;
|
||||
}
|
||||
</style>
|
||||
|
@ -11,6 +11,7 @@ found in the LICENSE.txt file.
|
||||
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
|
||||
<script src="../../js/js-test-pre.js"></script>
|
||||
<script src="../../js/webgl-test-utils.js"></script>
|
||||
<script src="../../js/tests/context-methods.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
@ -20,7 +21,7 @@ found in the LICENSE.txt file.
|
||||
"use strict";
|
||||
description("This test ensures that the WebGL context has all the methods in the specification.");
|
||||
|
||||
var methods = [
|
||||
const methods = [
|
||||
"getContextAttributes",
|
||||
"activeTexture",
|
||||
"attachShader",
|
||||
@ -159,55 +160,14 @@ var methods = [
|
||||
"viewport"
|
||||
];
|
||||
|
||||
// Properties to be ignored because they were added in versions of the
|
||||
// spec that are backward-compatible with this version
|
||||
var ignoredMethods = [
|
||||
// There is no official spec for the commit API yet, the proposal link is:
|
||||
// https://wiki.whatwg.org/wiki/OffscreenCanvas
|
||||
"commit"
|
||||
];
|
||||
|
||||
function assertFunction(v, f) {
|
||||
try {
|
||||
if (typeof v[f] != "function") {
|
||||
testFailed("Property either does not exist or is not a function: " + f);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} catch(e) {
|
||||
testFailed("Trying to access the property '" + f + "' threw an error: "+e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
debug("");
|
||||
debug("Canvas.getContext");
|
||||
|
||||
var wtu = WebGLTestUtils;
|
||||
var canvas = document.getElementById("canvas");
|
||||
var gl = wtu.create3DContext(canvas);
|
||||
var passed = true;
|
||||
for (var i=0; i<methods.length; i++) {
|
||||
var r = assertFunction(gl, methods[i]);
|
||||
passed = passed && r;
|
||||
}
|
||||
if (passed) {
|
||||
testPassed("All WebGL methods found.");
|
||||
}
|
||||
var extended = false;
|
||||
for (var i in gl) {
|
||||
if (typeof gl[i] == "function" && methods.indexOf(i) == -1 && ignoredMethods.indexOf(i) == -1) {
|
||||
if (!extended) {
|
||||
extended = true;
|
||||
testFailed("Also found the following extra methods:");
|
||||
}
|
||||
testFailed(i);
|
||||
}
|
||||
}
|
||||
const wtu = WebGLTestUtils;
|
||||
const canvas = document.getElementById("canvas");
|
||||
const gl = wtu.create3DContext(canvas);
|
||||
|
||||
if (!extended) {
|
||||
testPassed("No extra methods found on WebGL context.");
|
||||
}
|
||||
testContextMethods(gl, methods);
|
||||
|
||||
debug("");
|
||||
var successfullyParsed = true;
|
||||
|
@ -1,6 +1,7 @@
|
||||
--min-version 1.0.3 --max-version 1.9.9 angle-instanced-arrays.html
|
||||
--min-version 1.0.3 --max-version 1.9.9 angle-instanced-arrays-out-of-bounds.html
|
||||
--min-version 1.0.3 --max-version 1.9.9 ext-blend-minmax.html
|
||||
--min-version 1.0.4 ext-color-buffer-half-float.html
|
||||
--min-version 1.0.4 ext-float-blend.html
|
||||
--min-version 1.0.4 ext-texture-compression-bptc.html
|
||||
--min-version 1.0.4 ext-texture-compression-rgtc.html
|
||||
@ -10,6 +11,7 @@
|
||||
--min-version 1.0.3 --max-version 1.9.9 ext-sRGB.html
|
||||
--min-version 1.0.2 ext-texture-filter-anisotropic.html
|
||||
--min-version 1.0.2 get-extension.html
|
||||
--min-version 1.0.4 khr-parallel-shader-compile.html
|
||||
--max-version 1.9.9 oes-standard-derivatives.html
|
||||
--max-version 1.9.9 oes-texture-float-with-canvas.html
|
||||
--max-version 1.9.9 oes-texture-float-with-image-data.html
|
||||
@ -33,7 +35,7 @@ webgl-debug-shaders.html
|
||||
--min-version 1.0.4 webgl-compressed-texture-etc.html
|
||||
--min-version 1.0.4 webgl-compressed-texture-etc1.html
|
||||
--min-version 1.0.3 webgl-compressed-texture-pvrtc.html
|
||||
--min-version 1.0.2 webgl-compressed-texture-s3tc.html
|
||||
--min-version 1.0.4 s3tc-and-rgtc.html
|
||||
--min-version 1.0.4 webgl-compressed-texture-s3tc-srgb.html
|
||||
--min-version 1.0.3 webgl-compressed-texture-size-limit.html
|
||||
--min-version 1.0.2 --max-version 1.9.9 webgl-depth-texture.html
|
||||
|
@ -196,6 +196,9 @@ function runOutputTests() {
|
||||
0.0, 1.0, 0.0, 1.0, // Green
|
||||
0.0, 0.0, 1.0, 1.0, // Blue
|
||||
1.0, 1.0, 0.0, 1.0, // Yellow
|
||||
// extra data when colorLoc divisor is set back to 0
|
||||
1.0, 1.0, 0.0, 1.0, // Yellow
|
||||
1.0, 1.0, 0.0, 1.0, // Yellow
|
||||
]);
|
||||
var colorBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
|
||||
@ -277,6 +280,19 @@ function runOutputTests() {
|
||||
wtu.checkCanvasRect(gl, Math.ceil(0.25*canvas.width), 0, w, h, [0, 0, 255, 255]);
|
||||
wtu.checkCanvasRect(gl, Math.ceil(0.75*canvas.width), 0, w, h, [255, 255, 0, 255]);
|
||||
|
||||
debug("");
|
||||
debug("Testing drawArraysInstancedANGLE with attributes 'divisor' reset to 0");
|
||||
debug("Correct rendering output: 4 yellow triangles");
|
||||
debug("Possible incorrect rendering output: missing triangles, or triangles with different color at each vertex");
|
||||
ext.vertexAttribDivisorANGLE(colorLoc, 0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
ext.drawArraysInstancedANGLE(gl.TRIANGLES, 3, 3, instanceCount);
|
||||
wtu.checkCanvasRect(gl, Math.ceil(0.25*canvas.width), 0.5*canvas.height, w, h, [255, 255, 0, 255]);
|
||||
wtu.checkCanvasRect(gl, Math.ceil(0.75*canvas.width), 0.5*canvas.height, w, h, [255, 255, 0, 255]);
|
||||
wtu.checkCanvasRect(gl, Math.ceil(0.25*canvas.width), 0, w, h, [255, 255, 0, 255]);
|
||||
wtu.checkCanvasRect(gl, Math.ceil(0.75*canvas.width), 0, w, h, [255, 255, 0, 255]);
|
||||
ext.vertexAttribDivisorANGLE(colorLoc, 1);
|
||||
|
||||
wtu.setupUnitQuad(gl, 0);
|
||||
wtu.setupIndexedQuad(gl, 1, 0);
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, offsetBuffer);
|
||||
|
@ -0,0 +1,27 @@
|
||||
<!--
|
||||
Copyright (c) 2020 The Khronos Group Inc.
|
||||
Use of this source code is governed by an MIT-style license that can be
|
||||
found in the LICENSE.txt file.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>WebGL EXT_color_buffer_half_float Conformance Tests</title>
|
||||
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
|
||||
<script src="../../js/js-test-pre.js"></script>
|
||||
<script src="../../js/webgl-test-utils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
|
||||
<div id="console"></div>
|
||||
<script>
|
||||
var version = 1;
|
||||
</script>
|
||||
<script src="../../js/tests/ext-color-buffer-half-float.js"></script>
|
||||
<script src="../../js/js-test-post.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -60,7 +60,7 @@ function runTestExtension() {
|
||||
// * <height> is not a multiple of four, and <height> plus <yoffset> is
|
||||
// not equal to TEXTURE_HEIGHT; or
|
||||
// * <xoffset> or <yoffset> is not a multiple of four.
|
||||
ctu.testTexSubImageDimensions(gl, validFormats, expectedByteLength, getBlockDimensions,
|
||||
ctu.testTexSubImageDimensions(gl, ext, validFormats, expectedByteLength, getBlockDimensions,
|
||||
16, 16, [
|
||||
{ xoffset: 0, yoffset: 0, width: 4, height: 3,
|
||||
expectation: gl.INVALID_OPERATION, message: "height is not a multiple of 4" },
|
||||
@ -73,6 +73,63 @@ function runTestExtension() {
|
||||
{ xoffset: 12, yoffset: 12, width: 4, height: 4,
|
||||
expectation: gl.NO_ERROR, message: "is valid" },
|
||||
]);
|
||||
|
||||
// Test TexImage validation on level dimensions combinations.
|
||||
// When level equals 0, width and height must be a multiple of 4.
|
||||
// When level is larger than 0, this constraint doesn't apply.
|
||||
|
||||
let npotExpectation, npotMessage;
|
||||
if (contextVersion >= 2) {
|
||||
npotExpectation = gl.NO_ERROR;
|
||||
npotMessage = "valid";
|
||||
} else {
|
||||
npotExpectation = gl.INVALID_VALUE;
|
||||
npotMessage = "invalid";
|
||||
}
|
||||
|
||||
ctu.testTexImageLevelDimensions(gl, ext, validFormats, expectedByteLength, getBlockDimensions,
|
||||
[
|
||||
{ level: 0, width: 4, height: 3,
|
||||
expectation: gl.INVALID_OPERATION, message: "level is 0, height is not a multiple of 4" },
|
||||
{ level: 0, width: 3, height: 4,
|
||||
expectation: gl.INVALID_OPERATION, message: "level is 0, width is not a multiple of 4" },
|
||||
{ level: 0, width: 2, height: 2,
|
||||
expectation: gl.INVALID_OPERATION, message: "level is 0, width is not a multiple of 4" },
|
||||
{ level: 0, width: 4, height: 4,
|
||||
expectation: gl.NO_ERROR, message: "is valid" },
|
||||
{ level: 1, width: 1, height: 1,
|
||||
expectation: gl.INVALID_OPERATION, message: "implied base mip 2x2 is invalid" },
|
||||
{ level: 1, width: 1, height: 2,
|
||||
expectation: gl.INVALID_OPERATION, message: "implied base mip 2x4 is invalid" },
|
||||
{ level: 1, width: 2, height: 1,
|
||||
expectation: gl.INVALID_OPERATION, message: "implied base mip 4x2 is invalid" },
|
||||
{ level: 1, width: 2, height: 2,
|
||||
expectation: gl.NO_ERROR, message: "implied base mip 4x4 is valid" },
|
||||
{ level: 2, width: 1, height: 3,
|
||||
expectation: npotExpectation, message: "implied base mip 4x12 is " + npotMessage },
|
||||
]);
|
||||
|
||||
// Test that BPTC enums are not accepted by texImage2D
|
||||
{
|
||||
var tex = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex);
|
||||
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, ext.COMPRESSED_RGBA_BPTC_UNORM_EXT, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "COMPRESSED_RGBA_BPTC_UNORM_EXT fails with texImage2D");
|
||||
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, ext.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT fails with texImage2D");
|
||||
|
||||
if (contextVersion >= 2) {
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, ext.COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT, 4, 4, 0, gl.RGB, gl.FLOAT, null);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT fails with texImage2D");
|
||||
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, ext.COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT, 4, 4, 0, gl.RGB, gl.FLOAT, null);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT fails with texImage2D");
|
||||
}
|
||||
|
||||
gl.deleteTexture(tex);
|
||||
}
|
||||
};
|
||||
|
||||
function runTest() {
|
||||
|
@ -65,7 +65,7 @@ function runTestExtension() {
|
||||
// * <height> is not a multiple of four, and <height> plus <yoffset> is
|
||||
// not equal to TEXTURE_HEIGHT; or
|
||||
// * <xoffset> or <yoffset> is not a multiple of four.
|
||||
ctu.testTexSubImageDimensions(gl, validFormats, expectedByteLength, getBlockDimensions,
|
||||
ctu.testTexSubImageDimensions(gl, ext, validFormats, expectedByteLength, getBlockDimensions,
|
||||
16, 16, [
|
||||
{ xoffset: 0, yoffset: 0, width: 4, height: 3,
|
||||
expectation: gl.INVALID_OPERATION, message: "height is not a multiple of 4" },
|
||||
@ -78,6 +78,61 @@ function runTestExtension() {
|
||||
{ xoffset: 12, yoffset: 12, width: 4, height: 4,
|
||||
expectation: gl.NO_ERROR, message: "is valid" },
|
||||
]);
|
||||
|
||||
// Test TexImage validation on level dimensions combinations.
|
||||
// When level equals 0, width and height must be a multiple of 4.
|
||||
// When level is larger than 0, this constraint doesn't apply.
|
||||
|
||||
let npotExpectation, npotMessage;
|
||||
if (contextVersion >= 2) {
|
||||
npotExpectation = gl.NO_ERROR;
|
||||
npotMessage = "valid";
|
||||
} else {
|
||||
npotExpectation = gl.INVALID_VALUE;
|
||||
npotMessage = "invalid";
|
||||
}
|
||||
|
||||
ctu.testTexImageLevelDimensions(gl, ext, validFormats, expectedByteLength, getBlockDimensions,
|
||||
[
|
||||
{ level: 0, width: 4, height: 3,
|
||||
expectation: gl.INVALID_OPERATION, message: "level is 0, height is not a multiple of 4" },
|
||||
{ level: 0, width: 3, height: 4,
|
||||
expectation: gl.INVALID_OPERATION, message: "level is 0, width is not a multiple of 4" },
|
||||
{ level: 0, width: 2, height: 2,
|
||||
expectation: gl.INVALID_OPERATION, message: "level is 0, width is not a multiple of 4" },
|
||||
{ level: 0, width: 4, height: 4,
|
||||
expectation: gl.NO_ERROR, message: "is valid" },
|
||||
{ level: 1, width: 1, height: 1,
|
||||
expectation: gl.INVALID_OPERATION, message: "implied base mip 2x2 is invalid" },
|
||||
{ level: 1, width: 1, height: 2,
|
||||
expectation: gl.INVALID_OPERATION, message: "implied base mip 2x4 is invalid" },
|
||||
{ level: 1, width: 2, height: 1,
|
||||
expectation: gl.INVALID_OPERATION, message: "implied base mip 4x2 is invalid" },
|
||||
{ level: 1, width: 2, height: 2,
|
||||
expectation: gl.NO_ERROR, message: "implied base mip 4x4 is valid" },
|
||||
{ level: 2, width: 1, height: 3,
|
||||
expectation: npotExpectation, message: "implied base mip 4x12 is " + npotMessage },
|
||||
]);
|
||||
|
||||
// Test that RGTC enums are not accepted by texImage2D
|
||||
if (contextVersion >= 2) {
|
||||
var tex = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex);
|
||||
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, ext.COMPRESSED_RED_RGTC1_EXT, 4, 4, 0, gl.RED, gl.UNSIGNED_BYTE, null);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "COMPRESSED_RED_RGTC1_EXT fails with texImage2D");
|
||||
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, ext.COMPRESSED_SIGNED_RED_RGTC1_EXT, 4, 4, 0, gl.RED, gl.BYTE, null);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "COMPRESSED_SIGNED_RED_RGTC1_EXT fails with texImage2D");
|
||||
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, ext.COMPRESSED_RED_GREEN_RGTC2_EXT, 4, 4, 0, gl.RG, gl.UNSIGNED_BYTE, null);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "COMPRESSED_RED_GREEN_RGTC2_EXT fails with texImage2D");
|
||||
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, ext.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT, 4, 4, 0, gl.RG, gl.BYTE, null);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT fails with texImage2D");
|
||||
|
||||
gl.deleteTexture(tex);
|
||||
}
|
||||
};
|
||||
|
||||
function runTest() {
|
||||
|
@ -0,0 +1,220 @@
|
||||
<!--
|
||||
Copyright (c) 2020 The Khronos Group Inc.
|
||||
Use of this source code is governed by an MIT-style license that can be
|
||||
found in the LICENSE.txt file.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
|
||||
<script src="../../js/js-test-pre.js"></script>
|
||||
<script src="../../js/webgl-test-utils.js"></script>
|
||||
<style>
|
||||
.spinner {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
border: 20px solid transparent;
|
||||
border-top: 20px solid black;
|
||||
border-radius: 100%;
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
}
|
||||
@keyframes rotation {
|
||||
from { transorm: rotate(0); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
<button onclick='compileShaders()'>The spinners below should not stutter when you click this button.</button>
|
||||
<div class="spinner" style="animation: rotation 2s infinite linear;">CSS</div>
|
||||
<div class="spinner" id=spinner>JS</div>
|
||||
<div id="console"></div>
|
||||
<canvas id=canvas></canvas>
|
||||
<script>
|
||||
"use strict";
|
||||
description("Test KHR_parallel_shader_compile");
|
||||
|
||||
function spinSpinner() {
|
||||
let degrees = (performance.now() / 1000 / 2 % 1.) * 360;
|
||||
spinner.style.transform = `rotate(${degrees}deg)`;
|
||||
requestAnimationFrame(spinSpinner);
|
||||
}
|
||||
spinSpinner();
|
||||
|
||||
const wtu = WebGLTestUtils;
|
||||
|
||||
const gl = wtu.create3DContext();
|
||||
const loseContext = wtu.getExtensionWithKnownPrefixes(gl, "WEBGL_lose_context");
|
||||
|
||||
let counter = 0;
|
||||
const vertexSource = (extra) => `
|
||||
void main() {
|
||||
vec4 result = vec4(0.${counter++});
|
||||
${extra || ''}
|
||||
gl_Position = result;
|
||||
}`;
|
||||
const fragmentSource = (extra) => `
|
||||
precision highp float;
|
||||
void main() {
|
||||
vec4 result = vec4(0.${counter++});
|
||||
${extra || ''}
|
||||
gl_FragColor = result;
|
||||
}`;
|
||||
|
||||
let vs = gl.createShader(gl.VERTEX_SHADER);
|
||||
let fs = gl.createShader(gl.FRAGMENT_SHADER);
|
||||
let program = gl.createProgram();
|
||||
gl.attachShader(program, vs);
|
||||
gl.attachShader(program, fs);
|
||||
|
||||
const COMPLETION_STATUS_KHR = 0x91B1;
|
||||
|
||||
gl.shaderSource(vs, vertexSource());
|
||||
gl.compileShader(vs);
|
||||
let status = gl.getShaderParameter(vs, COMPLETION_STATUS_KHR);
|
||||
if (status !== null) testFailed('Extension disabled, status should be null');
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "extension disabled");
|
||||
|
||||
gl.shaderSource(fs, fragmentSource());
|
||||
gl.compileShader(fs);
|
||||
|
||||
gl.linkProgram(program);
|
||||
status = gl.getProgramParameter(program, COMPLETION_STATUS_KHR);
|
||||
if (status !== null) testFailed('Extension disabled, status should be null');
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "extension disabled");
|
||||
|
||||
const ext = wtu.getExtensionWithKnownPrefixes(gl, "KHR_parallel_shader_compile");
|
||||
|
||||
let successfullyParsed = false;
|
||||
|
||||
let extraCode = '';
|
||||
|
||||
(async () => {
|
||||
|
||||
if (!ext) {
|
||||
testPassed("No KHR_parallel_shader_compile support -- this is legal");
|
||||
} else {
|
||||
testPassed("Successfully enabled KHR_parallel_shader_compile extension");
|
||||
|
||||
shouldBe("ext.COMPLETION_STATUS_KHR", "0x91B1");
|
||||
|
||||
debug("Checking that status is a boolean.");
|
||||
gl.shaderSource(vs, vertexSource());
|
||||
gl.compileShader(vs);
|
||||
let status = gl.getShaderParameter(vs, COMPLETION_STATUS_KHR);
|
||||
if (status !== true && status !== false) testFailed("status should be a boolean");
|
||||
|
||||
gl.linkProgram(program);
|
||||
status = gl.getProgramParameter(program, COMPLETION_STATUS_KHR);
|
||||
if (status !== true && status !== false) testFailed("status should be a boolean");
|
||||
|
||||
const minimumShaderCompileDurationMs = 500;
|
||||
debug(`Constructing shader that takes > ${minimumShaderCompileDurationMs} ms to compile.`);
|
||||
let measuredCompileDuration = 0;
|
||||
extraCode = '\n if (true) { result += vec4(0.0000001); }';
|
||||
for (let i = 0; measuredCompileDuration < minimumShaderCompileDurationMs; i++) {
|
||||
extraCode += extraCode;
|
||||
extraCode += extraCode;
|
||||
if (i < 4) continue;
|
||||
gl.shaderSource(vs, vertexSource(extraCode));
|
||||
gl.shaderSource(fs, fragmentSource(extraCode));
|
||||
gl.compileShader(vs);
|
||||
gl.compileShader(fs);
|
||||
gl.linkProgram(program);
|
||||
const start = performance.now();
|
||||
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
||||
testFailed(`Shaders failed to compile.
|
||||
program: ${gl.getProgramInfoLog(program)}
|
||||
vs: ${gl.getShaderInfoLog(vs)}
|
||||
fs: ${gl.getShaderInfoLog(fs)}`);
|
||||
break;
|
||||
}
|
||||
measuredCompileDuration = performance.now() - start;
|
||||
}
|
||||
|
||||
debug('');
|
||||
gl.shaderSource(vs, vertexSource(extraCode));
|
||||
gl.shaderSource(fs, fragmentSource(extraCode));
|
||||
gl.compileShader(vs);
|
||||
gl.compileShader(fs);
|
||||
gl.linkProgram(program);
|
||||
|
||||
let start = performance.now();
|
||||
gl.getShaderParameter(fs, COMPLETION_STATUS_KHR);
|
||||
gl.getShaderParameter(vs, COMPLETION_STATUS_KHR);
|
||||
let duration = performance.now() - start;
|
||||
if (duration > 100)
|
||||
testFailed(`Querying shader status should not wait for compilation. Took ${duration} ms`);
|
||||
|
||||
let frames = 0;
|
||||
const maximumTimeToWait = measuredCompileDuration * 4;
|
||||
while (!gl.getProgramParameter(program, COMPLETION_STATUS_KHR)
|
||||
&& performance.now() - start < maximumTimeToWait) {
|
||||
frames++;
|
||||
await new Promise(requestAnimationFrame);
|
||||
}
|
||||
duration = performance.now() - start;
|
||||
if (!gl.getProgramParameter(program, COMPLETION_STATUS_KHR)) {
|
||||
testFailed(`Program took longer than ${maximumTimeToWait} ms to compile. Expected: ${measuredCompileDuration} ms, actual: ${duration} ms`);
|
||||
} else if (!gl.getShaderParameter(vs, COMPLETION_STATUS_KHR) || !gl.getShaderParameter(fs, COMPLETION_STATUS_KHR)) {
|
||||
testFailed('Program linked before shaders finished compiling.');
|
||||
} else if (frames <= 6) {
|
||||
testFailed(`Program should have taken many more than 6 frames to compile. Actual value: ${frames} frames, duration ${performance.now() - start} ms.`);
|
||||
} else {
|
||||
console.log(`COMPLETION_STATUS_KHR sucessfully transitioned from false to true in ${frames} frames and ${duration} ms.`);
|
||||
testPassed(`COMPLETION_STATUS_KHR sucessfully transitioned from false to true`);
|
||||
}
|
||||
|
||||
|
||||
debug("Checking that status is true when context is lost.");
|
||||
if (loseContext) {
|
||||
gl.shaderSource(vs, vertexSource(extraCode));
|
||||
gl.shaderSource(fs, fragmentSource(extraCode));
|
||||
gl.compileShader(vs);
|
||||
gl.compileShader(fs);
|
||||
gl.linkProgram(program);
|
||||
loseContext.loseContext();
|
||||
status = gl.getShaderParameter(vs, COMPLETION_STATUS_KHR);
|
||||
if (status !== true) testFailed("shader status should be true when context is lost");
|
||||
status = gl.getProgramParameter(program, COMPLETION_STATUS_KHR);
|
||||
if (status !== true) testFailed("program status should be true when context is lost");
|
||||
loseContext.restoreContext();
|
||||
vs = gl.createShader(gl.VERTEX_SHADER);
|
||||
fs = gl.createShader(gl.FRAGMENT_SHADER);
|
||||
program = gl.createProgram();
|
||||
}
|
||||
}
|
||||
finishTest();
|
||||
})();
|
||||
|
||||
async function compileShaders() {
|
||||
console.log('Compiling shaders');
|
||||
const gl = canvas.getContext('webgl');
|
||||
const vs = gl.createShader(gl.VERTEX_SHADER);
|
||||
const fs = gl.createShader(gl.FRAGMENT_SHADER);
|
||||
const program = gl.createProgram();
|
||||
gl.getExtension(wtu.getExtensionWithKnownPrefixes(gl, "KHR_parallel_shader_compile"));
|
||||
gl.attachShader(program, vs);
|
||||
gl.attachShader(program, fs);
|
||||
gl.shaderSource(vs, vertexSource(extraCode));
|
||||
gl.shaderSource(fs, fragmentSource(extraCode));
|
||||
gl.compileShader(vs);
|
||||
gl.compileShader(fs);
|
||||
gl.linkProgram(program);
|
||||
while (!gl.getProgramParameter(program, COMPLETION_STATUS_KHR)) {
|
||||
gl.getShaderParameter(vs, COMPLETION_STATUS_KHR);
|
||||
gl.getShaderParameter(fs, COMPLETION_STATUS_KHR);
|
||||
await new Promise(requestAnimationFrame);
|
||||
}
|
||||
gl.getProgramParameter(program, gl.LINK_STATUS);
|
||||
console.log('Compilation finished.');
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -25,7 +25,7 @@ const wtu = WebGLTestUtils;
|
||||
const gl = wtu.create3DContext();
|
||||
|
||||
(function() {
|
||||
if (!(gl instanceof WebGL2RenderingContext)) {
|
||||
if (!wtu.isWebGL2(gl)) {
|
||||
if (!gl.getExtension("OES_texture_float")) {
|
||||
testPassed("No OES_texture_float support -- this is legal");
|
||||
return;
|
||||
|
@ -25,7 +25,7 @@ const wtu = WebGLTestUtils;
|
||||
const gl = wtu.create3DContext();
|
||||
|
||||
(function() {
|
||||
if (gl instanceof WebGL2RenderingContext)
|
||||
if (wtu.isWebGL2(gl))
|
||||
throw new Error("OES_texture_half_float_linear is core in WebGL 2.");
|
||||
|
||||
const ext = gl.getExtension("OES_texture_half_float");
|
||||
|
@ -12,7 +12,7 @@ found in the LICENSE.txt file.
|
||||
<script src="../../js/js-test-pre.js"></script>
|
||||
<script src="../../js/webgl-test-utils.js"></script>
|
||||
<script src="../../js/tests/compressed-texture-utils.js"></script>
|
||||
<title>WebGL WEBGL_compressed_texture_s3tc Conformance Tests</title>
|
||||
<title>WebGL WEBGL_compressed_texture_s3tc and EXT_texture_compression_rgtc Conformance Tests</title>
|
||||
<style>
|
||||
img {
|
||||
border: 1px solid black;
|
||||
@ -35,7 +35,7 @@ img {
|
||||
<div id="console"></div>
|
||||
<script>
|
||||
"use strict";
|
||||
description("This test verifies the functionality of the WEBGL_compressed_texture_s3tc extension, if it is available.");
|
||||
description("This test verifies the functionality of the WEBGL_compressed_texture_s3tc extension, if it is available. It also tests the related formats from the EXT_texture_compression_rgtc extension.");
|
||||
|
||||
debug("");
|
||||
|
||||
@ -130,6 +130,31 @@ var img_4x4_rgba_dxt5 = new Uint8Array([
|
||||
0x00, 0xF8, 0xE0, 0x07, 0x1B, 0x5B, 0xAB, 0xFF
|
||||
]);
|
||||
|
||||
// BC4 - just the alpha block from BC3 above, interpreted as the red channel.
|
||||
// See http://www.reedbeta.com/blog/understanding-bcn-texture-compression-formats/#bc4
|
||||
// for format details.
|
||||
var img_4x4_r_bc4 = new Uint8Array([
|
||||
0xFF, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6,
|
||||
]);
|
||||
|
||||
// BC5 - Two BC3 alpha blocks, interpreted as the red and green channels.
|
||||
var img_4x4_rg_bc5 = new Uint8Array([
|
||||
0xFF, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6,
|
||||
0x00, 0xFF, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6,
|
||||
]);
|
||||
|
||||
// Signed BC4 - change endpoints to use full -1 to 1 range.
|
||||
var img_4x4_signed_r_bc4 = new Uint8Array([
|
||||
0x7F, 0x80, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6,
|
||||
]);
|
||||
|
||||
// Signed BC5 - Two BC3 alpha blocks, interpreted as the red and green channels.
|
||||
var img_4x4_signed_rg_bc5 = new Uint8Array([
|
||||
0x7F, 0x80, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6,
|
||||
0x80, 0x7F, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6,
|
||||
]);
|
||||
|
||||
|
||||
/*
|
||||
8x8 block endpoints use half-intensity values (appear darker than 4x4)
|
||||
*/
|
||||
@ -151,6 +176,18 @@ var img_8x8_rgba_dxt5 = new Uint8Array([
|
||||
0xff,0x69,0x00,0x00,0x00,0x01,0x10,0x00,0x0f,0x78,0xe0,0x03,0x11,0x10,0x15,0x00,
|
||||
0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0x03,0xef,0x00,0x11,0x10,0x15,0x00
|
||||
]);
|
||||
var img_8x8_r_bc4 = new Uint8Array([
|
||||
0x7F, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6,
|
||||
0x7F, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6,
|
||||
0x7F, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6,
|
||||
0x7F, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6,
|
||||
]);
|
||||
var img_8x8_rg_bc5 = new Uint8Array([
|
||||
0x7F, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6, 0x00, 0x7F, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6,
|
||||
0x7F, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6, 0x00, 0x7F, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6,
|
||||
0x7F, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6, 0x00, 0x7F, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6,
|
||||
0x7F, 0x00, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6, 0x00, 0x7F, 0x88, 0x16, 0x8D, 0x1A, 0x3B, 0xD6,
|
||||
]);
|
||||
|
||||
var wtu = WebGLTestUtils;
|
||||
var ctu = CompressedTextureUtils;
|
||||
@ -159,6 +196,7 @@ var canvas = document.getElementById("canvas");
|
||||
var gl = wtu.create3DContext(canvas, {antialias: false});
|
||||
var program = wtu.setupTexturedQuad(gl);
|
||||
var ext = null;
|
||||
var ext_rgtc = {};
|
||||
var vao = null;
|
||||
var validFormats = {
|
||||
COMPRESSED_RGB_S3TC_DXT1_EXT : 0x83F0,
|
||||
@ -188,6 +226,14 @@ if (!gl) {
|
||||
wtu.runExtensionSupportedTest(gl, "WEBGL_compressed_texture_s3tc", true);
|
||||
runTestExtension();
|
||||
}
|
||||
ext_rgtc = wtu.getExtensionWithKnownPrefixes(gl, "EXT_texture_compression_rgtc");
|
||||
if (ext_rgtc) {
|
||||
ext = ext || {};
|
||||
// Make ctu.formatToString work for rgtc enums.
|
||||
for (const name in ext_rgtc)
|
||||
ext[name] = ext_rgtc[name];
|
||||
runTestRGTC();
|
||||
}
|
||||
}
|
||||
|
||||
function expectedByteLength(width, height, format) {
|
||||
@ -221,6 +267,145 @@ function runTestExtension() {
|
||||
if (contextVersion >= 2) {
|
||||
testDXT5_RGBA_PBO();
|
||||
}
|
||||
|
||||
// Test TexImage validation on level dimensions combinations.
|
||||
debug("");
|
||||
debug("When level equals 0, width and height must be a multiple of 4.");
|
||||
debug("When level is larger than 0, this constraint doesn't apply.");
|
||||
ctu.testTexImageLevelDimensions(gl, ext, validFormats, expectedByteLength, getBlockDimensions,
|
||||
[
|
||||
{ level: 0, width: 4, height: 3, expectation: gl.INVALID_OPERATION, message: "0: 4x3" },
|
||||
{ level: 0, width: 3, height: 4, expectation: gl.INVALID_OPERATION, message: "0: 3x4" },
|
||||
{ level: 0, width: 2, height: 2, expectation: gl.INVALID_OPERATION, message: "0: 2x2" },
|
||||
{ level: 0, width: 4, height: 4, expectation: gl.NO_ERROR, message: "0: 4x4" },
|
||||
{ level: 1, width: 2, height: 2, expectation: gl.NO_ERROR, message: "1: 2x2" },
|
||||
{ level: 2, width: 1, height: 1, expectation: gl.NO_ERROR, message: "2: 1x1" },
|
||||
]);
|
||||
|
||||
ctu.testTexSubImageDimensions(gl, ext, validFormats, expectedByteLength, getBlockDimensions, 16, 16,
|
||||
[
|
||||
{ xoffset: 0, yoffset: 0, width: 4, height: 3,
|
||||
expectation: gl.INVALID_OPERATION, message: "height is not a multiple of 4" },
|
||||
{ xoffset: 0, yoffset: 0, width: 3, height: 4,
|
||||
expectation: gl.INVALID_OPERATION, message: "width is not a multiple of 4" },
|
||||
{ xoffset: 1, yoffset: 0, width: 4, height: 4,
|
||||
expectation: gl.INVALID_OPERATION, message: "xoffset is not a multiple of 4" },
|
||||
{ xoffset: 0, yoffset: 1, width: 4, height: 4,
|
||||
expectation: gl.INVALID_OPERATION, message: "yoffset is not a multiple of 4" },
|
||||
{ xoffset: 12, yoffset: 12, width: 4, height: 4,
|
||||
expectation: gl.NO_ERROR, message: "is valid" },
|
||||
]);
|
||||
|
||||
if (contextVersion >= 2) {
|
||||
debug("");
|
||||
debug("Testing NPOT textures");
|
||||
ctu.testTexImageLevelDimensions(gl, ext, validFormats, expectedByteLength, getBlockDimensions,
|
||||
[
|
||||
{ level: 0, width: 0, height: 0, expectation: gl.NO_ERROR, message: "0: 0x0 is valid" },
|
||||
{ level: 0, width: 1, height: 1, expectation: gl.INVALID_OPERATION, message: "0: 1x1 is invalid" },
|
||||
{ level: 0, width: 2, height: 2, expectation: gl.INVALID_OPERATION, message: "0: 2x2 is invalid" },
|
||||
{ level: 0, width: 3, height: 3, expectation: gl.INVALID_OPERATION, message: "0: 3x3 is invalid" },
|
||||
{ level: 0, width: 10, height: 10, expectation: gl.INVALID_OPERATION, message: "0: 10x10 is invalid" },
|
||||
{ level: 0, width: 11, height: 11, expectation: gl.INVALID_OPERATION, message: "0: 11x11 is invalid" },
|
||||
{ level: 0, width: 11, height: 12, expectation: gl.INVALID_OPERATION, message: "0: 11x12 is invalid" },
|
||||
{ level: 0, width: 12, height: 11, expectation: gl.INVALID_OPERATION, message: "0: 12x11 is invalid" },
|
||||
{ level: 0, width: 12, height: 12, expectation: gl.NO_ERROR, message: "0: 12x12 is valid" },
|
||||
{ level: 1, width: 0, height: 0, expectation: gl.NO_ERROR, message: "1: 0x0, is valid" },
|
||||
{ level: 1, width: 3, height: 3, expectation: gl.INVALID_OPERATION, message: "1: 3x3, is invalid" },
|
||||
{ level: 1, width: 5, height: 5, expectation: gl.INVALID_OPERATION, message: "1: 5x5, is invalid" },
|
||||
{ level: 1, width: 5, height: 6, expectation: gl.INVALID_OPERATION, message: "1: 5x6, is invalid" },
|
||||
{ level: 1, width: 6, height: 5, expectation: gl.INVALID_OPERATION, message: "1: 6x5, is invalid" },
|
||||
{ level: 1, width: 6, height: 6, expectation: gl.NO_ERROR, message: "1: 6x6, is valid" },
|
||||
{ level: 2, width: 0, height: 0, expectation: gl.NO_ERROR, message: "2: 0x0, is valid" },
|
||||
{ level: 2, width: 3, height: 3, expectation: gl.NO_ERROR, message: "2: 3x3, is valid" },
|
||||
{ level: 3, width: 1, height: 3, expectation: gl.NO_ERROR, message: "3: 1x3, is valid" },
|
||||
{ level: 3, width: 1, height: 1, expectation: gl.NO_ERROR, message: "3: 1x1, is valid" },
|
||||
]);
|
||||
|
||||
debug("");
|
||||
debug("Testing partial updates");
|
||||
ctu.testTexSubImageDimensions(gl, ext, validFormats, expectedByteLength, getBlockDimensions, 12, 12,
|
||||
[
|
||||
{ xoffset: 0, yoffset: 0, width: 4, height: 3,
|
||||
expectation: gl.INVALID_OPERATION, message: "height is not a multiple of 4" },
|
||||
{ xoffset: 0, yoffset: 0, width: 3, height: 4,
|
||||
expectation: gl.INVALID_OPERATION, message: "width is not a multiple of 4" },
|
||||
{ xoffset: 1, yoffset: 0, width: 4, height: 4,
|
||||
expectation: gl.INVALID_OPERATION, message: "xoffset is not a multiple of 4" },
|
||||
{ xoffset: 0, yoffset: 1, width: 4, height: 4,
|
||||
expectation: gl.INVALID_OPERATION, message: "yoffset is not a multiple of 4" },
|
||||
{ xoffset: 8, yoffset: 8, width: 4, height: 4,
|
||||
expectation: gl.NO_ERROR, message: "is valid" },
|
||||
]);
|
||||
|
||||
debug("");
|
||||
debug("Testing immutable NPOT textures");
|
||||
ctu.testTexStorageLevelDimensions(gl, ext, validFormats, expectedByteLength, getBlockDimensions,
|
||||
[
|
||||
{ width: 12, height: 12, expectation: gl.NO_ERROR, message: "0: 12x12 is valid" },
|
||||
{ width: 6, height: 6, expectation: gl.NO_ERROR, message: "1: 6x6, is valid" },
|
||||
{ width: 3, height: 3, expectation: gl.NO_ERROR, message: "2: 3x3, is valid" },
|
||||
{ width: 1, height: 1, expectation: gl.NO_ERROR, message: "3: 1x1, is valid" },
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
function runTestRGTC() {
|
||||
var tests = [
|
||||
{ width: 4,
|
||||
height: 4,
|
||||
channels: 1,
|
||||
data: img_4x4_r_bc4,
|
||||
format: ext_rgtc.COMPRESSED_RED_RGTC1_EXT,
|
||||
hasAlpha: false,
|
||||
},
|
||||
{ width: 4,
|
||||
height: 4,
|
||||
channels: 1,
|
||||
data: img_4x4_signed_r_bc4,
|
||||
format: ext_rgtc.COMPRESSED_SIGNED_RED_RGTC1_EXT,
|
||||
hasAlpha: false,
|
||||
},
|
||||
{ width: 4,
|
||||
height: 4,
|
||||
channels: 2,
|
||||
data: img_4x4_rg_bc5,
|
||||
format: ext_rgtc.COMPRESSED_RED_GREEN_RGTC2_EXT,
|
||||
hasAlpha: false,
|
||||
},
|
||||
{ width: 4,
|
||||
height: 4,
|
||||
channels: 2,
|
||||
data: img_4x4_signed_rg_bc5,
|
||||
format: ext_rgtc.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT,
|
||||
hasAlpha: false,
|
||||
},
|
||||
{ width: 8,
|
||||
height: 8,
|
||||
channels: 2,
|
||||
data: img_8x8_r_bc4,
|
||||
format: ext_rgtc.COMPRESSED_RED_RGTC1_EXT,
|
||||
hasAlpha: false,
|
||||
subX0: 0,
|
||||
subY0: 0,
|
||||
subWidth: 4,
|
||||
subHeight: 4,
|
||||
subData: img_4x4_r_bc4,
|
||||
},
|
||||
{ width: 8,
|
||||
height: 8,
|
||||
channels: 2,
|
||||
data: img_8x8_rg_bc5,
|
||||
format: ext_rgtc.COMPRESSED_RED_GREEN_RGTC2_EXT,
|
||||
hasAlpha: false,
|
||||
subX0: 0,
|
||||
subY0: 0,
|
||||
subWidth: 4,
|
||||
subHeight: 4,
|
||||
subData: img_4x4_rg_bc5,
|
||||
},
|
||||
];
|
||||
testDXTTextures(tests);
|
||||
}
|
||||
|
||||
function testDXT1_RGB() {
|
||||
@ -365,20 +550,29 @@ function uncompressDXTBlock(
|
||||
}
|
||||
return r;
|
||||
}
|
||||
var isDXT1 = format == ext.COMPRESSED_RGB_S3TC_DXT1_EXT ||
|
||||
format == ext.COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||
var colorOffset = srcOffset + (isDXT1 ? 0 : 8);
|
||||
var color0 = make565(src, colorOffset + 0);
|
||||
var color1 = make565(src, colorOffset + 2);
|
||||
var c0gtc1 = color0 > color1 || !isDXT1;
|
||||
var rgba0 = make8888From565(color0);
|
||||
var rgba1 = make8888From565(color1);
|
||||
var colors = [
|
||||
rgba0,
|
||||
rgba1,
|
||||
c0gtc1 ? mix(2, rgba0, rgba1, 3) : mix(1, rgba0, rgba1, 2),
|
||||
c0gtc1 ? mix(2, rgba1, rgba0, 3) : [0, 0, 0, 255]
|
||||
];
|
||||
var isBC45 = ext_rgtc &&
|
||||
(format == ext_rgtc.COMPRESSED_RED_RGTC1_EXT ||
|
||||
format == ext_rgtc.COMPRESSED_RED_GREEN_RGTC2_EXT ||
|
||||
format == ext_rgtc.COMPRESSED_SIGNED_RED_RGTC1_EXT ||
|
||||
format == ext_rgtc.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT);
|
||||
if (!isBC45) {
|
||||
var isDXT1 = format == ext.COMPRESSED_RGB_S3TC_DXT1_EXT ||
|
||||
format == ext.COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||
var colorOffset = srcOffset + (isDXT1 ? 0 : 8);
|
||||
var color0 = make565(src, colorOffset + 0);
|
||||
var color1 = make565(src, colorOffset + 2);
|
||||
var c0gtc1 = color0 > color1 || !isDXT1;
|
||||
var rgba0 = make8888From565(color0);
|
||||
var rgba1 = make8888From565(color1);
|
||||
var colors = [
|
||||
rgba0,
|
||||
rgba1,
|
||||
c0gtc1 ? mix(2, rgba0, rgba1, 3) : mix(1, rgba0, rgba1, 2),
|
||||
c0gtc1 ? mix(2, rgba1, rgba0, 3) : [0, 0, 0, 255]
|
||||
];
|
||||
}
|
||||
const isSigned = ext_rgtc && (format == ext_rgtc.COMPRESSED_SIGNED_RED_RGTC1_EXT || format == ext_rgtc.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT);
|
||||
const signedSrc = new Int8Array(src);
|
||||
|
||||
// yea I know there is a lot of math in this inner loop.
|
||||
// so sue me.
|
||||
@ -386,9 +580,57 @@ function uncompressDXTBlock(
|
||||
var pixels = src[colorOffset + 4 + yy];
|
||||
for (var xx = 0; xx < 4; ++xx) {
|
||||
var dstOff = ((destY + yy) * destWidth + destX + xx) * 4;
|
||||
var code = (pixels >> (xx * 2)) & 0x3;
|
||||
var srcColor = colors[code];
|
||||
if (!isBC45) {
|
||||
var code = (pixels >> (xx * 2)) & 0x3;
|
||||
var srcColor = colors[code];
|
||||
}
|
||||
var alpha;
|
||||
var rgChannel2 = 0;
|
||||
let decodeAlpha = (offset) => {
|
||||
let alpha;
|
||||
var alpha0 = (isSigned ? signedSrc : src)[offset + 0];
|
||||
var alpha1 = (isSigned ? signedSrc : src)[offset + 1];
|
||||
var alphaOff = (yy >> 1) * 3 + 2;
|
||||
var alphaBits =
|
||||
src[offset + alphaOff + 0] +
|
||||
src[offset + alphaOff + 1] * 256 +
|
||||
src[offset + alphaOff + 2] * 65536;
|
||||
var alphaShift = (yy % 2) * 12 + xx * 3;
|
||||
var alphaCode = (alphaBits >> alphaShift) & 0x7;
|
||||
if (alpha0 > alpha1) {
|
||||
switch (alphaCode) {
|
||||
case 0:
|
||||
alpha = alpha0;
|
||||
break;
|
||||
case 1:
|
||||
alpha = alpha1;
|
||||
break;
|
||||
default:
|
||||
alpha = Math.floor(((8 - alphaCode) * alpha0 + (alphaCode - 1) * alpha1) / 7.0 + 0.5);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (alphaCode) {
|
||||
case 0:
|
||||
alpha = alpha0;
|
||||
break;
|
||||
case 1:
|
||||
alpha = alpha1;
|
||||
break;
|
||||
case 6:
|
||||
alpha = 0;
|
||||
break;
|
||||
case 7:
|
||||
alpha = 255;
|
||||
break;
|
||||
default:
|
||||
alpha = Math.floor(((6 - alphaCode) * alpha0 + (alphaCode - 1) * alpha1) / 5.0 + 0.5);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return alpha;
|
||||
}
|
||||
|
||||
switch (format) {
|
||||
case ext.COMPRESSED_RGB_S3TC_DXT1_EXT:
|
||||
alpha = 255;
|
||||
@ -403,57 +645,33 @@ function uncompressDXTBlock(
|
||||
alpha = alpha1 | (alpha1 << 4);
|
||||
}
|
||||
break;
|
||||
case ext_rgtc.COMPRESSED_RED_GREEN_RGTC2_EXT:
|
||||
case ext_rgtc.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
|
||||
rgChannel2 = decodeAlpha(srcOffset + 8);
|
||||
// FALLTHROUGH
|
||||
case ext.COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
||||
{
|
||||
var alpha0 = src[srcOffset + 0];
|
||||
var alpha1 = src[srcOffset + 1];
|
||||
var alphaOff = (yy >> 1) * 3 + 2;
|
||||
var alphaBits =
|
||||
src[srcOffset + alphaOff + 0] +
|
||||
src[srcOffset + alphaOff + 1] * 256 +
|
||||
src[srcOffset + alphaOff + 2] * 65536;
|
||||
var alphaShift = (yy % 2) * 12 + xx * 3;
|
||||
var alphaCode = (alphaBits >> alphaShift) & 0x7;
|
||||
if (alpha0 > alpha1) {
|
||||
switch (alphaCode) {
|
||||
case 0:
|
||||
alpha = alpha0;
|
||||
break;
|
||||
case 1:
|
||||
alpha = alpha1;
|
||||
break;
|
||||
default:
|
||||
alpha = Math.floor(((8 - alphaCode) * alpha0 + (alphaCode - 1) * alpha1) / 7.0 + 0.5);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (alphaCode) {
|
||||
case 0:
|
||||
alpha = alpha0;
|
||||
break;
|
||||
case 1:
|
||||
alpha = alpha1;
|
||||
break;
|
||||
case 6:
|
||||
alpha = 0;
|
||||
break;
|
||||
case 7:
|
||||
alpha = 255;
|
||||
break;
|
||||
default:
|
||||
alpha = Math.floor(((6 - alphaCode) * alpha0 + (alphaCode - 1) * alpha1) / 5.0 + 0.5);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
case ext_rgtc.COMPRESSED_RED_RGTC1_EXT:
|
||||
case ext_rgtc.COMPRESSED_SIGNED_RED_RGTC1_EXT:
|
||||
alpha = decodeAlpha(srcOffset);
|
||||
break;
|
||||
default:
|
||||
throw "bad format";
|
||||
}
|
||||
destBuffer[dstOff + 0] = srcColor[0];
|
||||
destBuffer[dstOff + 1] = srcColor[1];
|
||||
destBuffer[dstOff + 2] = srcColor[2];
|
||||
destBuffer[dstOff + 3] = alpha;
|
||||
if (isBC45) {
|
||||
destBuffer[dstOff + 0] = alpha;
|
||||
destBuffer[dstOff + 1] = rgChannel2;
|
||||
destBuffer[dstOff + 2] = 0;
|
||||
destBuffer[dstOff + 3] = 255;
|
||||
if (isSigned) {
|
||||
destBuffer[dstOff + 0] = Math.max(0, alpha) * 2;
|
||||
destBuffer[dstOff + 1] = Math.max(0, rgChannel2) * 2;
|
||||
}
|
||||
} else {
|
||||
destBuffer[dstOff + 0] = srcColor[0];
|
||||
destBuffer[dstOff + 1] = srcColor[1];
|
||||
destBuffer[dstOff + 2] = srcColor[2];
|
||||
destBuffer[dstOff + 3] = alpha;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -461,7 +679,8 @@ function uncompressDXTBlock(
|
||||
function getBlockSize(format) {
|
||||
var isDXT1 = format == ext.COMPRESSED_RGB_S3TC_DXT1_EXT ||
|
||||
format == ext.COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||
return isDXT1 ? 8 : 16;
|
||||
var isBC4 = ext_rgtc && (format == ext_rgtc.COMPRESSED_RED_RGTC1_EXT || format == ext_rgtc.COMPRESSED_SIGNED_RED_RGTC1_EXT);
|
||||
return isDXT1 || isBC4 ? 8 : 16;
|
||||
}
|
||||
|
||||
function uncompressDXT(width, height, data, format) {
|
||||
@ -487,8 +706,10 @@ function uncompressDXTIntoSubRegion(width, height, subX0, subY0, subWidth, subHe
|
||||
throw "bad dimension";
|
||||
|
||||
var dest = new Uint8Array(width * height * 4);
|
||||
// Zero-filled DXT1 texture represents [0, 0, 0, 255]
|
||||
if (format == ext.COMPRESSED_RGB_S3TC_DXT1_EXT || format == ext.COMPRESSED_RGBA_S3TC_DXT1_EXT) {
|
||||
// Zero-filled DXT1 or BC4/5 texture represents [0, 0, 0, 255]
|
||||
if (format == ext.COMPRESSED_RGB_S3TC_DXT1_EXT || format == ext.COMPRESSED_RGBA_S3TC_DXT1_EXT ||
|
||||
format == ext.COMPRESSED_RED_RGTC1_EXT || format == ext.COMPRESSED_SIGNED_RED_RGTC1_EXT ||
|
||||
format == ext.COMPRESSED_RED_GREEN_RGTC2_EXT || format == ext.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT) {
|
||||
for (var i = 3; i < dest.length; i += 4) dest[i] = 255;
|
||||
}
|
||||
var blocksAcross = subWidth / 4;
|
||||
@ -612,14 +833,16 @@ function testDXTTexture(test, useTexStorage) {
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
|
||||
|
||||
if (width == 4) {
|
||||
// The width/height of the implied base level must be a multiple of the block size.
|
||||
gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, 1, height, 0, data);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions for level 1");
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions for level > 0");
|
||||
gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, 2, height, 0, data);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0");
|
||||
}
|
||||
if (height == 4) {
|
||||
// The width/height of the implied base level must be a multiple of the block size.
|
||||
gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, width, 1, 0, data);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions for level 1");
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions for level > 0");
|
||||
gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, width, 2, 0, data);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0");
|
||||
}
|
||||
@ -640,6 +863,14 @@ function testDXTTexture(test, useTexStorage) {
|
||||
case ext.COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
||||
wrongFormat = ext.COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
||||
break;
|
||||
case ext_rgtc.COMPRESSED_RED_RGTC1_EXT:
|
||||
case ext_rgtc.COMPRESSED_SIGNED_RED_RGTC1_EXT:
|
||||
wrongFormat = ext_rgtc.COMPRESSED_RED_GREEN_RGTC2_EXT;
|
||||
break;
|
||||
case ext_rgtc.COMPRESSED_RED_GREEN_RGTC2_EXT:
|
||||
case ext_rgtc.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
|
||||
wrongFormat = ext_rgtc.COMPRESSED_RED_RGTC1_EXT;
|
||||
break;
|
||||
}
|
||||
|
||||
gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, wrongFormat, data);
|
@ -252,7 +252,7 @@ function testPVRTCTexture(test) {
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture");
|
||||
gl.generateMipmap(gl.TEXTURE_2D);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "trying to generate mipmaps from compressed texture");
|
||||
wtu.drawQuad(gl);
|
||||
wtu.clearAndDrawUnitQuad(gl);
|
||||
compareRect(width, height, test.channels, width, height, uncompressedData, data, format, undefined, "NEAREST");
|
||||
// Test again with linear filtering.
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
||||
|
@ -226,6 +226,72 @@ function runTestExtension() {
|
||||
if (contextVersion >= 2) {
|
||||
testDXT5_SRGB_ALPHA_PBO();
|
||||
}
|
||||
|
||||
// Test TexImage validation on level dimensions combinations.
|
||||
debug("");
|
||||
debug("When level equals 0, width and height must be a multiple of 4.");
|
||||
debug("When level is larger than 0, this constraint doesn't apply.");
|
||||
ctu.testTexImageLevelDimensions(gl, ext, validFormats, expectedByteLength, getBlockDimensions,
|
||||
[
|
||||
{ level: 0, width: 4, height: 3, expectation: gl.INVALID_OPERATION, message: "0: 4x3" },
|
||||
{ level: 0, width: 3, height: 4, expectation: gl.INVALID_OPERATION, message: "0: 3x4" },
|
||||
{ level: 0, width: 2, height: 2, expectation: gl.INVALID_OPERATION, message: "0: 2x2" },
|
||||
{ level: 0, width: 4, height: 4, expectation: gl.NO_ERROR, message: "0: 4x4" },
|
||||
{ level: 1, width: 2, height: 2, expectation: gl.NO_ERROR, message: "1: 2x2" },
|
||||
{ level: 2, width: 1, height: 1, expectation: gl.NO_ERROR, message: "2: 1x1" },
|
||||
]);
|
||||
|
||||
ctu.testTexSubImageDimensions(gl, ext, validFormats, expectedByteLength, getBlockDimensions, 16, 16,
|
||||
[
|
||||
{ xoffset: 0, yoffset: 0, width: 4, height: 3,
|
||||
expectation: gl.INVALID_OPERATION, message: "height is not a multiple of 4" },
|
||||
{ xoffset: 0, yoffset: 0, width: 3, height: 4,
|
||||
expectation: gl.INVALID_OPERATION, message: "width is not a multiple of 4" },
|
||||
{ xoffset: 1, yoffset: 0, width: 4, height: 4,
|
||||
expectation: gl.INVALID_OPERATION, message: "xoffset is not a multiple of 4" },
|
||||
{ xoffset: 0, yoffset: 1, width: 4, height: 4,
|
||||
expectation: gl.INVALID_OPERATION, message: "yoffset is not a multiple of 4" },
|
||||
{ xoffset: 12, yoffset: 12, width: 4, height: 4,
|
||||
expectation: gl.NO_ERROR, message: "is valid" },
|
||||
]);
|
||||
|
||||
if (contextVersion >= 2) {
|
||||
debug("");
|
||||
debug("Testing NPOT textures");
|
||||
ctu.testTexImageLevelDimensions(gl, ext, validFormats, expectedByteLength, getBlockDimensions,
|
||||
[
|
||||
{ level: 0, width: 12, height: 12, expectation: gl.NO_ERROR, message: "0: 12x12 is valid" },
|
||||
{ level: 1, width: 6, height: 6, expectation: gl.NO_ERROR, message: "1: 6x6, is valid" },
|
||||
{ level: 2, width: 3, height: 3, expectation: gl.NO_ERROR, message: "2: 3x3, is valid" },
|
||||
{ level: 3, width: 1, height: 1, expectation: gl.NO_ERROR, message: "3: 1x1, is valid" },
|
||||
]);
|
||||
|
||||
debug("");
|
||||
debug("Testing partial updates");
|
||||
ctu.testTexSubImageDimensions(gl, ext, validFormats, expectedByteLength, getBlockDimensions, 12, 12,
|
||||
[
|
||||
{ xoffset: 0, yoffset: 0, width: 4, height: 3,
|
||||
expectation: gl.INVALID_OPERATION, message: "height is not a multiple of 4" },
|
||||
{ xoffset: 0, yoffset: 0, width: 3, height: 4,
|
||||
expectation: gl.INVALID_OPERATION, message: "width is not a multiple of 4" },
|
||||
{ xoffset: 1, yoffset: 0, width: 4, height: 4,
|
||||
expectation: gl.INVALID_OPERATION, message: "xoffset is not a multiple of 4" },
|
||||
{ xoffset: 0, yoffset: 1, width: 4, height: 4,
|
||||
expectation: gl.INVALID_OPERATION, message: "yoffset is not a multiple of 4" },
|
||||
{ xoffset: 8, yoffset: 8, width: 4, height: 4,
|
||||
expectation: gl.NO_ERROR, message: "is valid" },
|
||||
]);
|
||||
|
||||
debug("");
|
||||
debug("Testing immutable NPOT textures");
|
||||
ctu.testTexStorageLevelDimensions(gl, ext, validFormats, expectedByteLength, getBlockDimensions,
|
||||
[
|
||||
{ width: 12, height: 12, expectation: gl.NO_ERROR, message: "0: 12x12 is valid" },
|
||||
{ width: 6, height: 6, expectation: gl.NO_ERROR, message: "1: 6x6, is valid" },
|
||||
{ width: 3, height: 3, expectation: gl.NO_ERROR, message: "2: 3x3, is valid" },
|
||||
{ width: 1, height: 1, expectation: gl.NO_ERROR, message: "3: 1x1, is valid" },
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
function testDXT1_SRGB() {
|
||||
@ -617,14 +683,16 @@ function testDXTTexture(test, useTexStorage) {
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
|
||||
|
||||
if (width == 4) {
|
||||
// The width/height of the implied base level must be a multiple of the block size.
|
||||
gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, 1, height, 0, data);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions for level 1");
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions for level > 0");
|
||||
gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, 2, height, 0, data);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0");
|
||||
}
|
||||
if (height == 4) {
|
||||
// The width/height of the implied base level must be a multiple of the block size.
|
||||
gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, width, 1, 0, data);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions for level 1");
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions for level > 0");
|
||||
gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, width, 2, 0, data);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0");
|
||||
}
|
||||
|
@ -146,6 +146,7 @@ const wtu = WebGLTestUtils;
|
||||
const canvas = document.getElementById("canvas");
|
||||
const gl = wtu.create3DContext(canvas);
|
||||
const instancedExt = gl && gl.getExtension('ANGLE_instanced_arrays');
|
||||
const bufferUsageSet = [ gl.STATIC_DRAW, gl.DYNAMIC_DRAW ];
|
||||
|
||||
// Check if the extension is either both enabled and supported or
|
||||
// not enabled and not supported.
|
||||
@ -187,18 +188,18 @@ function runTest() {
|
||||
|
||||
function doTest(ext, instanced) {
|
||||
|
||||
function runValidationTests() {
|
||||
function runValidationTests(bufferUsage) {
|
||||
const vertexBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0.2,0.2, 0.8,0.2, 0.5,0.8 ]), gl.STATIC_DRAW);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0.2,0.2, 0.8,0.2, 0.5,0.8 ]), bufferUsage);
|
||||
|
||||
const indexBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
|
||||
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array([ 0, 1, 2, 0]), gl.STATIC_DRAW);
|
||||
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array([ 0, 1, 2, 0]), bufferUsage);
|
||||
|
||||
const instanceBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, instanceBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0, 1, 2, 3 ]), gl.STATIC_DRAW);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0, 1, 2, 3 ]), bufferUsage);
|
||||
|
||||
const program = wtu.setupProgram(gl, ["vshaderNoDrawID", "fshader"], ["vPosition", "vInstance"], [0, 1]);
|
||||
expectTrue(program != null, "can compile simple program");
|
||||
@ -354,7 +355,7 @@ function doTest(ext, instanced) {
|
||||
}
|
||||
}
|
||||
|
||||
function runShaderTests() {
|
||||
function runShaderTests(bufferUsage) {
|
||||
const illegalProgram = wtu.setupProgram(gl, ["vshaderIllegalDrawID", "fshader"], ["vPosition"], [0]);
|
||||
expectTrue(illegalProgram == null, "cannot compile program with gl_DrawID but no extension directive");
|
||||
|
||||
@ -363,14 +364,14 @@ function doTest(ext, instanced) {
|
||||
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.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0, 1,0, 0,1, 0,1, 1,0, 1,1 ]), bufferUsage);
|
||||
gl.enableVertexAttribArray(0);
|
||||
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
|
||||
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
||||
wtu.checkCanvas(gl, [0, 255, 0, 255], "gl_DrawID is 0 for non-Multi* draw calls", 0);
|
||||
}
|
||||
|
||||
function runPixelTests() {
|
||||
function runPixelTests(bufferUsage, useSharedArrayBuffer) {
|
||||
// An array of quads is tiled across the screen.
|
||||
// gl_DrawID is checked by using it to select the color of the draw.
|
||||
// Instanced entrypoints are tested here scaling and then instancing the
|
||||
@ -438,16 +439,16 @@ function doTest(ext, instanced) {
|
||||
const instanceBuffer = gl.createBuffer();
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, nonIndexedVertexBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, nonIndexedVertices, gl.STATIC_DRAW);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, nonIndexedVertices, bufferUsage);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, vertices, bufferUsage);
|
||||
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
|
||||
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
|
||||
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, bufferUsage);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, instanceBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1, 2, 3, 4]), gl.STATIC_DRAW);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1, 2, 3, 4]), bufferUsage);
|
||||
|
||||
function checkResult(config, msg) {
|
||||
const rects = [];
|
||||
@ -505,10 +506,18 @@ function doTest(ext, instanced) {
|
||||
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);
|
||||
function newIntArray(count) {
|
||||
if (!useSharedArrayBuffer) {
|
||||
return new Int32Array(count);
|
||||
}
|
||||
let sab = new SharedArrayBuffer(count * Int32Array.BYTES_PER_ELEMENT);
|
||||
return new Int32Array(sab);
|
||||
}
|
||||
|
||||
const firsts = newIntArray(tri_count);
|
||||
const counts = newIntArray(tri_count);
|
||||
const offsets = newIntArray(tri_count);
|
||||
const instances = newIntArray(tri_count);
|
||||
|
||||
for (let i = 0; i < firsts.length; ++i) firsts[i] = i * 3;
|
||||
counts.fill(3);
|
||||
@ -520,7 +529,7 @@ function doTest(ext, instanced) {
|
||||
const offsetsOffset = countsOffset + counts.length;
|
||||
const instancesOffset = offsetsOffset + instances.length;
|
||||
|
||||
const buffer = new Uint32Array(firstsOffset + firsts.length + counts.length + offsets.length + instances.length);
|
||||
const buffer = newIntArray(firstsOffset + firsts.length + counts.length + offsets.length + instances.length);
|
||||
buffer.set(firsts, firstsOffset);
|
||||
buffer.set(counts, countsOffset);
|
||||
buffer.set(offsets, offsetsOffset);
|
||||
@ -663,6 +672,8 @@ function doTest(ext, instanced) {
|
||||
config.instanced ? ' instanced' : ''
|
||||
) + (
|
||||
config.drawID ? ' with gl_DrawID' : ''
|
||||
) + (
|
||||
useSharedArrayBuffer ? ' and SharedArrayBuffer' : ''
|
||||
));
|
||||
|
||||
gl.disableVertexAttribArray(0);
|
||||
@ -821,9 +832,18 @@ function doTest(ext, instanced) {
|
||||
}
|
||||
}
|
||||
|
||||
runValidationTests();
|
||||
runShaderTests();
|
||||
runPixelTests();
|
||||
for (let i = 0; i < bufferUsageSet.length; i++) {
|
||||
let bufferUsage = bufferUsageSet[i];
|
||||
debug("Testing with BufferUsage = " + bufferUsage);
|
||||
runValidationTests(bufferUsage);
|
||||
runShaderTests(bufferUsage);
|
||||
runPixelTests(bufferUsage, false);
|
||||
}
|
||||
|
||||
// Run a subset of the pixel tests with SharedArrayBuffer if supported.
|
||||
if (window.SharedArrayBuffer) {
|
||||
runPixelTests(bufferUsageSet[0], true);
|
||||
}
|
||||
}
|
||||
|
||||
runTest();
|
||||
|
@ -0,0 +1,211 @@
|
||||
<!--
|
||||
Copyright (c) 2021 The Khronos Group Inc.
|
||||
Use of this source code is governed by an MIT-style license that can be
|
||||
found in the LICENSE.txt file.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" href="../../resources/js-test-style.css" />
|
||||
<script src="../../js/js-test-pre.js"></script>
|
||||
<script src="../../js/webgl-test-utils.js"></script>
|
||||
<script src="../../js/tests/out-of-bounds-test.js"></script>
|
||||
<script src="../../../../extensions/proposals/WEBGL_webcodecs_video_frame/webgl_webcodecs_video_frame.js"></script>
|
||||
<style>
|
||||
canvas {
|
||||
padding: 10px;
|
||||
background: gold;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: #555555;
|
||||
border: none;
|
||||
color: white;
|
||||
padding: 15px 32px;
|
||||
width: 150px;
|
||||
text-align: center;
|
||||
display: block;
|
||||
font-size: 16px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<canvas id="src" width="640" height="480"></canvas>
|
||||
<canvas id="dst" width="640" height="480"></canvas>
|
||||
<p id="info"></p>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<script>
|
||||
"use strict";
|
||||
description("Test of importing Videoframe from Webcodecs to Webgl");
|
||||
|
||||
const kIsRunningTest = true;
|
||||
const kMaxFrame = 10;
|
||||
const kTestPixel = [255, 128, 0, 255];
|
||||
// Sum of pixel difference of R/G/B channel. Use to decide whether a
|
||||
// pixel is matched with another.
|
||||
const codec_string = "vp09.00.51.08.00";
|
||||
|
||||
let wtu = WebGLTestUtils;
|
||||
let cnv = document.getElementById("src");
|
||||
let src_width = cnv.width;
|
||||
let src_height = cnv.height;
|
||||
let src_color = "rgba(" + kTestPixel[0].toString() + "," + kTestPixel[1].toString() + ","
|
||||
+ kTestPixel[2].toString() + "," + kTestPixel[3].toString() + ")";
|
||||
let frame_counter = 0;
|
||||
let pixelCompareTolerance = 5;
|
||||
|
||||
function getQueryVariable(variable) {
|
||||
var query = window.location.search.substring(1);
|
||||
var vars = query.split("&");
|
||||
for (var i = 0; i < vars.length; i++) {
|
||||
var pair = vars[i].split("=");
|
||||
if (pair[0] == variable) { return pair[1]; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
let th = parseInt(getQueryVariable('threshold'));
|
||||
if (!isNaN(th))
|
||||
pixelCompareTolerance = th;
|
||||
|
||||
async function startDrawing() {
|
||||
let cnv = document.getElementById("src");
|
||||
var ctx = cnv.getContext('2d', { alpha: false });
|
||||
|
||||
ctx.fillStyle = src_color;
|
||||
let drawOneFrame = function (time) {
|
||||
ctx.fillStyle = src_color;
|
||||
ctx.fillRect(0, 0, src_width, src_height);
|
||||
window.requestAnimationFrame(drawOneFrame);
|
||||
}
|
||||
window.requestAnimationFrame(drawOneFrame);
|
||||
}
|
||||
|
||||
function captureAndEncode(processChunk) {
|
||||
let cnv = document.getElementById("src");
|
||||
let fps = 60;
|
||||
let pending_outputs = 0;
|
||||
let stream = cnv.captureStream(fps);
|
||||
let processor = new MediaStreamTrackProcessor(stream.getVideoTracks()[0]);
|
||||
|
||||
const init = {
|
||||
output: (chunk) => {
|
||||
testPassed("Encode frame successfully.");
|
||||
pending_outputs--;
|
||||
processChunk(chunk);
|
||||
},
|
||||
error: (e) => {
|
||||
testFailed("Failed to encode frame.");
|
||||
finishTest();
|
||||
vtr.stop();
|
||||
}
|
||||
};
|
||||
|
||||
const config = {
|
||||
codec: codec_string,
|
||||
width: cnv.width,
|
||||
height: cnv.height,
|
||||
bitrate: 10e6,
|
||||
framerate: fps,
|
||||
};
|
||||
|
||||
let encoder = new VideoEncoder(init);
|
||||
encoder.configure(config);
|
||||
|
||||
const frame_reader = processor.readable.getReader();
|
||||
frame_reader.read().then(function processFrame({done, value}) {
|
||||
if (done)
|
||||
return;
|
||||
|
||||
if (pending_outputs > 30) {
|
||||
console.log("drop this frame");
|
||||
// Too many frames in flight, encoder is overwhelmed
|
||||
// let's drop this frame.
|
||||
value.close();
|
||||
frame_reader.read().then(processFrame);
|
||||
return;
|
||||
}
|
||||
|
||||
if(frame_counter == kMaxFrame) {
|
||||
frame_reader.releaseLock();
|
||||
processor.readable.cancel();
|
||||
value.close();
|
||||
return;
|
||||
}
|
||||
|
||||
frame_counter++;
|
||||
pending_outputs++;
|
||||
const insert_keyframe = (frame_counter % 150) == 0;
|
||||
encoder.encode(value, { keyFrame: insert_keyframe });
|
||||
|
||||
frame_reader.read().then(processFrame);
|
||||
});
|
||||
}
|
||||
|
||||
function startDecodingAndRendering(cnv, handleFrame) {
|
||||
const init = {
|
||||
output: handleFrame,
|
||||
error: (e) => {
|
||||
testFailed("Failed to decode frame.");
|
||||
finishTest();
|
||||
}
|
||||
};
|
||||
|
||||
const config = {
|
||||
codec: codec_string,
|
||||
codedWidth: cnv.width,
|
||||
codedHeight: cnv.height,
|
||||
acceleration: "deny",
|
||||
|
||||
};
|
||||
|
||||
let decoder = new VideoDecoder(init);
|
||||
decoder.configure(config);
|
||||
return decoder;
|
||||
}
|
||||
|
||||
function isFramePixelMatched(gl, th_per_pixel = pixelCompareTolerance) {
|
||||
WebGLTestUtils.checkCanvasRect(gl, 0, 0, src_width, src_width, kTestPixel, "should be orange", pixelCompareTolerance)
|
||||
}
|
||||
|
||||
function main() {
|
||||
if (!("VideoEncoder" in window)) {
|
||||
testPassed("WebCodecs API is not supported.");
|
||||
finishTest();
|
||||
return;
|
||||
}
|
||||
let cnv = document.getElementById("dst");
|
||||
|
||||
let webgl_webcodecs_test_context = {
|
||||
maxFrameTested: kMaxFrame,
|
||||
displayed_frame: 0,
|
||||
isFramePixelMatched: isFramePixelMatched,
|
||||
testFailed: testFailed,
|
||||
testPassed: testPassed,
|
||||
finishTest: finishTest
|
||||
};
|
||||
setTestMode(webgl_webcodecs_test_context);
|
||||
let handleFrame = requestWebGLVideoFrameHandler(cnv);
|
||||
if (handleFrame === null) {
|
||||
finishTest();
|
||||
return;
|
||||
}
|
||||
|
||||
startDrawing();
|
||||
let decoder = startDecodingAndRendering(cnv, handleFrame);
|
||||
captureAndEncode((chunk) => {
|
||||
decoder.decode(chunk);
|
||||
});
|
||||
}
|
||||
|
||||
document.body.onload = main;
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
@ -5,6 +5,7 @@
|
||||
--min-version 1.0.3 array-of-struct-with-int-first-position.html
|
||||
--min-version 1.0.4 assign-to-swizzled-twice-in-function.html
|
||||
--min-version 1.0.4 bool-type-cast-bug-int-float.html
|
||||
--min-version 1.0.4 character-set.html
|
||||
--min-version 1.0.3 compare-loop-index-to-uniform.html
|
||||
--min-version 1.0.3 complex-glsl-does-not-crash.html
|
||||
--min-version 1.0.4 compound-assignment-type-combination.html
|
||||
@ -46,5 +47,6 @@
|
||||
--min-version 1.0.4 undefined-index-should-not-crash.html
|
||||
--min-version 1.0.3 uniforms-should-not-lose-values.html
|
||||
--min-version 1.0.4 varying-arrays-should-not-be-reversed.html
|
||||
--min-version 1.0.4 vector-matrix-constructor-scalarization.html
|
||||
--min-version 1.0.4 vector-scalar-arithmetic-inside-loop.html
|
||||
--min-version 1.0.4 vector-scalar-arithmetic-inside-loop-complex.html
|
||||
--min-version 1.0.4 vector-scalar-arithmetic-inside-loop-complex.html
|
||||
|
@ -54,7 +54,7 @@ if (!gl) {
|
||||
debug("");
|
||||
debug("Checking shader compilation and linking.");
|
||||
|
||||
checkCompilation()
|
||||
checkCompilation();
|
||||
}
|
||||
|
||||
function checkCompilation() {
|
||||
|
@ -0,0 +1,115 @@
|
||||
<!--
|
||||
Copyright (c) 2020 The Khronos Group Inc.
|
||||
Use of this source code is governed by an MIT-style license that can be
|
||||
found in the LICENSE.txt file.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Character Set</title>
|
||||
<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
|
||||
<script src="../../../js/js-test-pre.js"></script>
|
||||
<script src="../../../js/webgl-test-utils.js"></script>
|
||||
<script src="../../../js/glsl-conformance-test.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<canvas id="canvas" width="2" height="2"> </canvas>
|
||||
<script>
|
||||
"use strict";
|
||||
// See http://crbug.com/1108588 for original failing case.
|
||||
// Check "OpenGL Registry The OpenGL ES Shading Language"
|
||||
// Section 3.2 Character Sets For more info
|
||||
description("This test checks character set validation for glsl.");
|
||||
|
||||
debug("");
|
||||
debug("Canvas.getContext");
|
||||
|
||||
let wtu = WebGLTestUtils;
|
||||
let gl = wtu.create3DContext("canvas");
|
||||
let consoleDiv = document.getElementById("console");
|
||||
if (!gl) {
|
||||
testFailed("context does not exist");
|
||||
} else {
|
||||
testPassed("context exists");
|
||||
|
||||
debug("");
|
||||
debug("Checking shader character set validation and compilation");
|
||||
|
||||
runTest();
|
||||
}
|
||||
|
||||
function testShaderSource(shaderSource, msg) {
|
||||
if (!quietMode()) {
|
||||
wtu.addShaderSource(consoleDiv, "test fragment shader", shaderSource);
|
||||
}
|
||||
|
||||
let shader = gl.createShader(gl.FRAGMENT_SHADER);
|
||||
if (shader == null) {
|
||||
testFailed("*** Error: unable to create shader '" + shaderSource + "'");
|
||||
return;
|
||||
}
|
||||
|
||||
gl.shaderSource(shader, shaderSource);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR, msg);
|
||||
}
|
||||
|
||||
function MUST(ifTruthy) {
|
||||
return ifTruthy ? 'MUST' : 'MUST NOT';
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
|
||||
const BAD_STRINGS = [
|
||||
'$',
|
||||
'"',
|
||||
'一些注释',
|
||||
'#line 42 "foo.glsl"',
|
||||
];
|
||||
const TESTS = [
|
||||
['in identifier', s => s, false],
|
||||
['in comment', s => `// ${s}`, true, true],
|
||||
['in ifdef-out', s => `#if 0 \n${s} \n#endif`, true],
|
||||
['in ifdef-out #preproc', s => `#if 0 \n#${s} \n#endif`, true],
|
||||
['in #preproc', s => `#${s}`, false],
|
||||
['in comment after #define', s => `#define TEST // ${s}`, true], // Regression test for crbug.com/940865
|
||||
];
|
||||
|
||||
const glsl_tests = [];
|
||||
|
||||
for (const s of BAD_STRINGS) {
|
||||
for (const [where, template, validCompile] of TESTS) {
|
||||
const st = template(s);
|
||||
const src = `
|
||||
precision mediump float;
|
||||
${st}
|
||||
void main() {
|
||||
gl_FragColor = vec4(1, 0, 0, 1);
|
||||
}`.trim();
|
||||
|
||||
testShaderSource(src, `shaderSource allows Out-of-charset string '${s}' ${where} until compilation.`);
|
||||
|
||||
glsl_tests.push(
|
||||
{
|
||||
fShaderSource: src,
|
||||
fShaderSuccess: validCompile,
|
||||
linkSuccess: validCompile,
|
||||
passMsg: `Out-of-charset string '${s}' ${where} ${MUST(validCompile)} compile.`
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
GLSLConformanceTester.runTests(glsl_tests);
|
||||
}
|
||||
|
||||
debug("");
|
||||
var successfullyParsed = true;
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,181 @@
|
||||
<!--
|
||||
Copyright (c) 2021 The Khronos Group Inc.
|
||||
Use of this source code is governed by an MIT-style license that can be
|
||||
found in the LICENSE.txt file.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title></title>
|
||||
<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
|
||||
<script src="../../../js/js-test-pre.js"></script>
|
||||
<script src="../../../js/webgl-test-utils.js"></script>
|
||||
|
||||
<!--
|
||||
|
||||
Original Shadertoy:
|
||||
https://www.shadertoy.com/view/ttGyzh
|
||||
|
||||
float a = 0.; // bug
|
||||
#define A 0. // ok
|
||||
//#define A min(0.,iTime) // bug
|
||||
|
||||
|
||||
#define r(a) mat2( cos( a + vec4(0,-1.5708,1.5708,0) ) ) // bug
|
||||
//#define r(a) mat2( cos(a), -sin(a), sin(a), cos(a) ) // no bug
|
||||
//#define r(a) cos(a),sin(a)) // no bug ( vec instead of mat )
|
||||
//#define r(a) cos(a+vec2(0,-1.5708)) // no bug ( vec instead of mat )
|
||||
|
||||
vec2 c;
|
||||
#define f(U,a) ( c = (U) * r(a) , sin(10.*c.x) )
|
||||
|
||||
void mainImage( out vec4 O, vec2 U )
|
||||
{
|
||||
U /= iResolution.xy;
|
||||
|
||||
O = U.y > .5
|
||||
? vec4( f(U,a) , f(U*4.,a) , 0,0) // top
|
||||
: vec4( f(U,A) , f(U*4.,A) , 0,0); // bottom
|
||||
}
|
||||
-->
|
||||
|
||||
<script id="vshader" type="x-shader/x-vertex">
|
||||
attribute vec2 aPosition;
|
||||
attribute vec2 aTexCoord;
|
||||
|
||||
varying vec2 vTexCoord;
|
||||
|
||||
void main(void) {
|
||||
gl_Position = vec4(aPosition, 0.0, 1.0);
|
||||
vTexCoord = aTexCoord;
|
||||
}
|
||||
</script>
|
||||
<script id="fshader" type="x-shader/x-fragment">
|
||||
precision mediump float;
|
||||
|
||||
varying vec2 vTexCoord;
|
||||
|
||||
float a = 0.;
|
||||
#define A 0.
|
||||
|
||||
#define r(a) mat2( cos( a + vec4(0,-1.5708,1.5708,0) ) )
|
||||
vec2 c;
|
||||
#define f(U,a) ( c = (U) * r(a) , sin(10.*c.x) )
|
||||
|
||||
void main() {
|
||||
vec2 U = vTexCoord;
|
||||
|
||||
gl_FragColor = U.y > .5
|
||||
? vec4( f(U,a) , f(U*4.,a) , 0,1.0) // top
|
||||
: vec4( f(U,A) , f(U*4.,A) , 0,1.0); // bottom
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="compileVShader" type="x-shader/x-vertex">
|
||||
varying vec2 v_texcoord;
|
||||
|
||||
void main() {
|
||||
v_texcoord = vec2(0.0, 0.0);
|
||||
gl_Position = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
</script>
|
||||
<script id="compileFShader" type="x-shader/x-fragment">
|
||||
// From http://crbug.com/398694
|
||||
precision mediump float;
|
||||
uniform sampler2D s_texture;
|
||||
uniform vec4 color_weights;
|
||||
varying vec2 v_texcoord;
|
||||
void main() {
|
||||
gl_FragColor = color_weights * mat4(
|
||||
vec4(texture2D(s_texture, v_texcoord).rgb, 1.0),
|
||||
vec4(texture2D(s_texture, v_texcoord).rgb, 1.0),
|
||||
vec4(texture2D(s_texture, v_texcoord).rgb, 1.0),
|
||||
vec4(texture2D(s_texture, v_texcoord).rgb, 1.0));
|
||||
}
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="example"></canvas>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<script>
|
||||
"use strict";
|
||||
debug("");
|
||||
|
||||
description("Vector and matrix constructor scalarization workaround (SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS) caused bugs");
|
||||
debug('Regression test for <a href="http://crbug.com/1165751">crbug.com/1165751</a>');
|
||||
|
||||
// Note: Firefox reports that without this workaround, there are
|
||||
// failures on at least Windows / Intel GPU / OpenGL on:
|
||||
// conformance/glsl/constructors/glsl-construct-mat2.html
|
||||
// https://searchfox.org/mozilla-central/source/dom/canvas/WebGLShaderValidator.cpp#63
|
||||
|
||||
// Chromium reported that
|
||||
// conformance/glsl/misc/shader-struct-scope.html failed on macOS and
|
||||
// on Linux AMD without this workaround enabled:
|
||||
// http://crbug.com/angleproject/701
|
||||
|
||||
const wtu = WebGLTestUtils;
|
||||
const canvas = document.getElementById("example");
|
||||
const sz = canvas.width = canvas.height = 256;
|
||||
const gl = wtu.create3DContext(canvas, undefined);
|
||||
|
||||
if (!gl) {
|
||||
testFailed("WebGL context creation failed");
|
||||
finishTest();
|
||||
} else {
|
||||
testPassed("WebGL context creation succeeded");
|
||||
runDrawTest();
|
||||
runCompileTest();
|
||||
finishTest();
|
||||
}
|
||||
|
||||
function runDrawTest() {
|
||||
debug("Ensure that shader translation isn't broken by the vector and matrix constructor scalarization workaround");
|
||||
let positionLocation = 0;
|
||||
let texCoordLocation = 1;
|
||||
wtu.setupUnitQuad(gl, positionLocation, texCoordLocation);
|
||||
let program = wtu.setupProgram(gl, ["vshader", "fshader"],
|
||||
["aPosition", "aTexCoord"],
|
||||
[positionLocation, texCoordLocation], true);
|
||||
if (!program) {
|
||||
testFailed("Error compiling shaders");
|
||||
return;
|
||||
}
|
||||
gl.useProgram(program);
|
||||
// Buffers returned from setupQuad above, and ignored, are already bound.
|
||||
wtu.drawUnitQuad(gl);
|
||||
|
||||
// Top and bottom halves should be roughly equal. Go through one
|
||||
// horizontal scanline in the middle.
|
||||
const compareHeight = sz / 4;
|
||||
let pixelValue = new Uint8Array(4);
|
||||
let allEqual = true;
|
||||
// Empirically found that tolerance between the top and bottom
|
||||
// needs to be up to roughly 8 on some platforms.
|
||||
const tolerance = 8;
|
||||
let tempBuf = new Uint8Array(4);
|
||||
// Step over some pixels to spew slightly fewer comparison messages.
|
||||
for (let x = 0; x < sz; x += 4) {
|
||||
gl.readPixels(x, compareHeight, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixelValue);
|
||||
wtu.checkCanvasRect(gl, x, sz - compareHeight, 1, 1, pixelValue, undefined, tolerance, tempBuf);
|
||||
}
|
||||
}
|
||||
|
||||
function runCompileTest() {
|
||||
debug("Running compilation test");
|
||||
let program = wtu.setupProgram(gl, ["compileVShader", "compileFShader"], [], [], true);
|
||||
if (program) {
|
||||
testPassed("Shader previously requiring SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS compiled successfully");
|
||||
} else {
|
||||
testFailed("Shader previously requiring SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS failed to compile");
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -49,6 +49,5 @@ void main()
|
||||
GLSLConformanceTester.runRenderTest();
|
||||
var successfullyParsed = true;
|
||||
</script>
|
||||
<script src="../../../js/js-test-post.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -38,7 +38,6 @@ shader-with-clipvertex.vert.html
|
||||
--min-version 1.0.2 shader-with-conditional-scoping-negative.html
|
||||
shader-with-default-precision.frag.html
|
||||
shader-with-default-precision.vert.html
|
||||
--max-version 1.9.9 shader-with-define-line-continuation.frag.html
|
||||
shader-with-dfdx-no-ext.frag.html
|
||||
shader-with-dfdx.frag.html
|
||||
--min-version 1.0.2 shader-with-do-loop.html
|
||||
|
@ -18,20 +18,35 @@ found in the LICENSE.txt file.
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<script id="vertexShader" type="text/something-not-javascript">
|
||||
// Non ascii comments in source should succeed
|
||||
// これはASCIIではないです。
|
||||
// This Is Not ASCII
|
||||
/*
|
||||
* This Is Not ASCII
|
||||
*/
|
||||
#define TEST 1 // <20>スs<EFBDBD>ス<EFBFBD>ス<EFBFBD>ス<EFBFBD>ス<EFBFBD>ス<EFBFBD>ス<EFBFBD>ス@<40>スh<EFBDBD>ス<EFBFBD>ス<EFBFBD>ス@<40>スm<EFBDBD>ス<EFBFBD>ス<EFBFBD>ス<EFBFBD>ス<EFBFBD>ス@<40>ス`<60>スr<EFBDBD>スb<EFBDBD>スh<EFBDBD>スh
|
||||
void main() {
|
||||
gl_Position = vec4(1,1,1,1); // <20>スs<EFBDBD>ス<EFBFBD>ス<EFBFBD>ス<EFBFBD>ス<EFBFBD>ス<EFBFBD>ス<EFBFBD>ス@<40>スh<EFBDBD>ス<EFBFBD>ス<EFBFBD>ス@<40>スm<EFBDBD>ス<EFBFBD>ス<EFBFBD>ス<EFBFBD>ス<EFBFBD>ス@<40>ス`<60>スr<EFBDBD>スb<EFBDBD>スh<EFBDBD>スh
|
||||
} // <20>スs<EFBDBD>ス<EFBFBD>ス<EFBFBD>ス<EFBFBD>ス<EFBFBD>ス<EFBFBD>ス<EFBFBD>ス@<40>スh<EFBDBD>ス<EFBFBD>ス<EFBFBD>ス@<40>スm<EFBDBD>ス<EFBFBD>ス<EFBFBD>ス<EFBFBD>ス<EFBFBD>ス@<40>ス`<60>スr<EFBDBD>スb<EFBDBD>スh<EFBDBD>スh
|
||||
<script id="vertexShader" type="text/plain">
|
||||
Loading...
|
||||
</script>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
// Via `[].map.call(str, x => x.codePointAt(0));`
|
||||
let a = [12371,12428,12399,65313,65331,65315,65321,65321,12391,12399,12394,12356,12391,12377,12290];
|
||||
let b = [65332,65352,65353,65363,12288,65321,65363,12288,65326,65359,65364,12288,65313,65331,65315,65321,65321];
|
||||
a = String.fromCodePoint(...a);
|
||||
b = String.fromCodePoint(...b);
|
||||
|
||||
// -
|
||||
|
||||
vertexShader.textContent = `
|
||||
// Non ascii comments in source should succeed
|
||||
// ${a}
|
||||
// ${b}
|
||||
/*
|
||||
* ${b}
|
||||
*/
|
||||
#define TEST 1 // ${b}
|
||||
void main() {
|
||||
gl_Position = vec4(1,1,1,1); // ${b}
|
||||
} // ${b}
|
||||
`;
|
||||
|
||||
// -
|
||||
|
||||
GLSLConformanceTester.runTest();
|
||||
var successfullyParsed = true;
|
||||
</script>
|
||||
|
@ -18,18 +18,35 @@ found in the LICENSE.txt file.
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<script id="vertexShader" type="text/something-not-javascript">
|
||||
// Non ascii data in source should fail
|
||||
// See GLSL ES Spec 1.0.17 section 3.1 and 3.2
|
||||
// これはASCIIではないです。
|
||||
// This Is Not ASCII
|
||||
uniform mat4 NotASCII;
|
||||
void main() {
|
||||
gl_Position = vec4(1,1,1,1);
|
||||
}
|
||||
<script id="vertexShader" type="text/plain">
|
||||
Loading...
|
||||
</script>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
// Via `[].map.call(str, x => x.codePointAt(0));`
|
||||
let a = [12371,12428,12399,65313,65331,65315,65321,65321,12391,12399,12394,12356,12391,12377,12290];
|
||||
let b = [65332,65352,65353,65363,12288,65321,65363,12288,65326,65359,65364,12288,65313,65331,65315,65321,65321];
|
||||
let c = [65326,65359,65364,65313,65331,65315,65321,65321];
|
||||
a = String.fromCodePoint(...a);
|
||||
b = String.fromCodePoint(...b);
|
||||
c = String.fromCodePoint(...c);
|
||||
|
||||
// -
|
||||
|
||||
vertexShader.textContent = `
|
||||
// Non ascii data in source should fail
|
||||
// See GLSL ES Spec 1.0.17 section 3.1 and 3.2
|
||||
// ${a}
|
||||
// ${b}
|
||||
uniform mat4 ${c};
|
||||
void main() {
|
||||
gl_Position = vec4(1,1,1,1);
|
||||
}
|
||||
`;
|
||||
|
||||
// -
|
||||
|
||||
GLSLConformanceTester.runTest();
|
||||
var successfullyParsed = true;
|
||||
</script>
|
||||
|
@ -1,37 +0,0 @@
|
||||
<!--
|
||||
Copyright (c) 2019 The Khronos Group Inc.
|
||||
Use of this source code is governed by an MIT-style license that can be
|
||||
found in the LICENSE.txt file.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>WebGL GLSL Conformance Tests</title>
|
||||
<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
|
||||
<link rel="stylesheet" href="../../../resources/glsl-feature-tests.css"/>
|
||||
<script src="../../../js/js-test-pre.js"></script>
|
||||
<script src="../../../js/webgl-test-utils.js"></script>
|
||||
<script src="../../../js/glsl-conformance-test.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<script id="fragmentShader" type="text/something-not-javascript">
|
||||
// fragment shader that uses line continuation macro should fail
|
||||
#define foo this \
|
||||
is a test
|
||||
precision mediump float;
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = vec4(0.0,0.0,0.0,1.0);
|
||||
}
|
||||
</script>
|
||||
<script>
|
||||
"use strict";
|
||||
GLSLConformanceTester.runTest();
|
||||
var successfullyParsed = true;
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -39,7 +39,13 @@ void main()
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
GLSL 1.017 section 4.2.6
|
||||
This test previously concluded that an attribute in a vertex shader
|
||||
would conflict across shaders with a uniform of the same name in the
|
||||
fragment shader, based on the following sections of the GLSL ES 1.0.17
|
||||
specification:
|
||||
|
||||
---
|
||||
Section 4.2.6
|
||||
|
||||
...
|
||||
|
||||
@ -56,16 +62,15 @@ Attribute variables are required to have global scope
|
||||
Section 4.3.4
|
||||
|
||||
The uniform qualifier is used to declare global variables
|
||||
---
|
||||
|
||||
QED: If both uniforms and attributes are in the global namespace they
|
||||
conflict across shaders
|
||||
GLSL ES 3.00 later confirmed that pipeline stages have distinct
|
||||
namespaces. The OpenGL ES working group confirmed in discussions
|
||||
https://github.com/KhronosGroup/WebGL/issues/3201 that this was the
|
||||
intended behavior for GLSL ES 1.00.
|
||||
|
||||
Note: This was brought up on the OpenGL ES working group and confirmed
|
||||
that the spec required these conflicts to fail to link.
|
||||
|
||||
Though most drivers allow this to work, some drivers to do no therefore
|
||||
WebGL implementation must enforce this restriction to provide consistent
|
||||
behavior.
|
||||
For this reason, this test asserts that such usage does not generate a
|
||||
conflict.
|
||||
*/
|
||||
|
||||
GLSLConformanceTester.runTests([
|
||||
@ -73,8 +78,8 @@ GLSLConformanceTester.runTests([
|
||||
vShaderSuccess: true,
|
||||
fShaderId: 'fragmentShader',
|
||||
fShaderSuccess: true,
|
||||
linkSuccess: false,
|
||||
passMsg: 'shaders with conflicting uniform/attribute names should fail'
|
||||
linkSuccess: true,
|
||||
passMsg: 'using the same name for a vertex shader attribute and fragment shader uniform should succeed'
|
||||
},
|
||||
]);
|
||||
var successfullyParsed = true;
|
||||
|
@ -126,12 +126,15 @@ for (var i = 0; i < invalidSet.length; ++i) {
|
||||
// Backslash as line-continuation is allowed in WebGL 2.0.
|
||||
if (contextVersion > 1 && invalidSet[i] == '\\')
|
||||
continue;
|
||||
// With recent specification changes from
|
||||
// https://github.com/KhronosGroup/WebGL/pull/3206 , shaderSource no
|
||||
// longer generates INVALID_VALUE.
|
||||
var validShaderSource = generateShaderSource(undefined, invalidSet[i]);
|
||||
context.shaderSource(vShader, validShaderSource);
|
||||
shouldBe("context.getError()", "context.NO_ERROR");
|
||||
var invalidShaderSource = generateShaderSource(invalidSet[i], undefined);
|
||||
context.shaderSource(vShader, invalidShaderSource);
|
||||
shouldBe("context.getError()", "context.INVALID_VALUE");
|
||||
shouldBe("context.getError()", "context.NO_ERROR");
|
||||
}
|
||||
|
||||
debug("");
|
||||
|
@ -128,6 +128,209 @@ shouldBeTrue('shaderPrecisionFormat.rangeMin == shaderPrecisionFormat2.rangeMin'
|
||||
shouldBeTrue('shaderPrecisionFormat.rangeMax == shaderPrecisionFormat2.rangeMax');
|
||||
shouldBeTrue('shaderPrecisionFormat.precision == shaderPrecisionFormat2.precision');
|
||||
|
||||
debug("");
|
||||
debug("Test that specified precision matches rendering results");
|
||||
debug("");
|
||||
|
||||
function testRenderPrecisionSetup(gl, shaderPair) {
|
||||
const program = wtu.setupProgram(gl, shaderPair);
|
||||
|
||||
// Create a buffer and setup an attribute.
|
||||
// We wouldn't need this except for a bug in Safari and arguably
|
||||
// this should be removed from the test but we can't test the test itself
|
||||
// without until the bug is fixed.
|
||||
// see https://bugs.webkit.org/show_bug.cgi?id=197592
|
||||
{
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
|
||||
gl.bufferData(gl.ARRAY_BUFFER, 1, gl.STATIC_DRAW);
|
||||
const loc = gl.getAttribLocation(program, 'position');
|
||||
gl.enableVertexAttribArray(loc);
|
||||
gl.vertexAttribPointer(loc, 1, gl.UNSIGNED_BYTE, false, 0, 0);
|
||||
}
|
||||
|
||||
gl.useProgram(program);
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
function testRenderPrecision(gl, shaderType, type, precision, expected, msg) {
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
gl.drawArrays(gl.POINTS, 0, 1);
|
||||
|
||||
const pixel = new Uint8Array(4);
|
||||
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
|
||||
|
||||
wtu.checkCanvasRect(gl, 0, 0, 1, 1, expected, msg, 5);
|
||||
}
|
||||
|
||||
function testRenderPrecisionFloat(gl, precisionEnum, precision) {
|
||||
function test(gl, shaderPair, shaderType) {
|
||||
const format = gl.getShaderPrecisionFormat(shaderType, precisionEnum);
|
||||
const value = 2 ** format.precision - 1;
|
||||
|
||||
const length = v => Math.sqrt(v.reduce((sum, v) => sum + v * v, 0));
|
||||
const normalize = (v) => {
|
||||
const l = length(v);
|
||||
return v.map(v => v / l);
|
||||
};
|
||||
|
||||
const input = [Math.sqrt(value), Math.sqrt(value), Math.sqrt(value)];
|
||||
const expected = [...normalize(input).map(v => (v * 0.5 + 0.5) * 255 | 0), 255];
|
||||
|
||||
const msg = `${wtu.glEnumToString(gl, shaderType)}: ${precision} float precision: ${format.precision}, rangeMin: ${format.rangeMin}, rangeMax: ${format.rangeMax}`;
|
||||
const program = testRenderPrecisionSetup(gl, shaderPair);
|
||||
const vLocation = gl.getUniformLocation(program, 'v');
|
||||
gl.uniform3fv(vLocation, input);
|
||||
testRenderPrecision(gl, shaderType, 'float', precision, expected, msg);
|
||||
}
|
||||
|
||||
{
|
||||
const vs = `
|
||||
attribute vec4 position;
|
||||
uniform ${precision} vec3 v;
|
||||
varying ${precision} vec4 v_result;
|
||||
void main() {
|
||||
gl_Position = position;
|
||||
gl_PointSize = 1.0;
|
||||
v_result = vec4(normalize(v) * 0.5 + 0.5, 1);
|
||||
}
|
||||
`;
|
||||
|
||||
const fs = `
|
||||
precision ${precision} float;
|
||||
varying ${precision} vec4 v_result;
|
||||
void main() {
|
||||
gl_FragColor = v_result;
|
||||
}
|
||||
`;
|
||||
|
||||
test(gl, [vs, fs], gl.VERTEX_SHADER);
|
||||
}
|
||||
|
||||
{
|
||||
const vs = `
|
||||
attribute vec4 position;
|
||||
void main() {
|
||||
gl_Position = position;
|
||||
gl_PointSize = 1.0;
|
||||
}
|
||||
`;
|
||||
|
||||
const fs = `
|
||||
precision ${precision} float;
|
||||
uniform ${precision} vec3 v;
|
||||
void main() {
|
||||
gl_FragColor = vec4(normalize(v) * 0.5 + 0.5, 1);
|
||||
}
|
||||
`;
|
||||
|
||||
test(gl, [vs, fs], gl.FRAGMENT_SHADER);
|
||||
}
|
||||
}
|
||||
|
||||
function testRenderPrecisionInt(gl, precisionEnum, precision) {
|
||||
function test(gl, shaderPair, shaderType) {
|
||||
const format = gl.getShaderPrecisionFormat(shaderType, precisionEnum);
|
||||
const value = 1 << (format.rangeMax - 1);
|
||||
|
||||
const input = [value, value, value, value];
|
||||
const expected = [255, 255, 255, 255];
|
||||
|
||||
const msg = `${wtu.glEnumToString(gl, shaderType)}: ${precision} int precision: ${format.precision}, rangeMin: ${format.rangeMin}, rangeMax: ${format.rangeMax}`;
|
||||
const program = testRenderPrecisionSetup(gl, shaderPair);
|
||||
gl.uniform1i(gl.getUniformLocation(program, 'v'), value);
|
||||
gl.uniform1f(gl.getUniformLocation(program, 'f'), value);
|
||||
testRenderPrecision(gl, shaderType, 'int', precision, expected, msg);
|
||||
}
|
||||
|
||||
{
|
||||
const vs = `
|
||||
attribute vec4 position;
|
||||
uniform ${precision} int v;
|
||||
uniform highp float f;
|
||||
varying vec4 v_result;
|
||||
|
||||
void main() {
|
||||
gl_Position = position;
|
||||
gl_PointSize = 1.0;
|
||||
float diff = abs(float(v) - f);
|
||||
bool pass = diff < 1.0;
|
||||
v_result = vec4(pass);
|
||||
}
|
||||
`;
|
||||
|
||||
const fs = `
|
||||
precision mediump float;
|
||||
varying vec4 v_result;
|
||||
void main() {
|
||||
gl_FragColor = v_result;
|
||||
}
|
||||
`;
|
||||
test(gl, [vs, fs], gl.VERTEX_SHADER);
|
||||
}
|
||||
|
||||
{
|
||||
const vs = `
|
||||
attribute vec4 position;
|
||||
void main() {
|
||||
gl_Position = position;
|
||||
gl_PointSize = 1.0;
|
||||
}
|
||||
`;
|
||||
|
||||
const fs = `
|
||||
precision ${precision} float;
|
||||
uniform ${precision} int v;
|
||||
uniform mediump float f;
|
||||
|
||||
void main() {
|
||||
mediump float diff = abs(float(v) - f);
|
||||
bool pass = diff < 1.0;
|
||||
gl_FragColor = vec4(pass);
|
||||
}
|
||||
`;
|
||||
|
||||
test(gl, [vs, fs], gl.FRAGMENT_SHADER);
|
||||
}
|
||||
}
|
||||
|
||||
// because the canvas can be 16 bit IIRC
|
||||
const fb = gl.createFramebuffer(gl.FRAMEBUFFER);
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
|
||||
|
||||
const tex = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
||||
|
||||
gl.framebufferTexture2D(
|
||||
gl.FRAMEBUFFER,
|
||||
gl.COLOR_ATTACHMENT0,
|
||||
gl.TEXTURE_2D,
|
||||
tex,
|
||||
0);
|
||||
|
||||
gl.viewport(0, 0, 1, 1);
|
||||
|
||||
{
|
||||
testRenderPrecisionFloat(gl, gl.LOW_FLOAT, 'lowp');
|
||||
testRenderPrecisionFloat(gl, gl.MEDIUM_FLOAT, 'mediump');
|
||||
|
||||
const format = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT);
|
||||
if (format.precision !== 0) {
|
||||
testRenderPrecisionFloat(gl, gl.HIGH_FLOAT, 'highp');
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
testRenderPrecisionInt(gl, gl.LOW_INT, 'lowp');
|
||||
testRenderPrecisionInt(gl, gl.MEDIUM_INT, 'mediump');
|
||||
|
||||
const format = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_INT);
|
||||
if (format.rangeMax !== 0) {
|
||||
testRenderPrecisionInt(gl, gl.HIGH_INT, 'highp');
|
||||
}
|
||||
}
|
||||
|
||||
finishTest();
|
||||
</script>
|
||||
|
||||
|
@ -178,6 +178,75 @@ gl.deleteTexture(tex);
|
||||
gl.finish();
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR);
|
||||
|
||||
debug("");
|
||||
debug("Reading an uninitialized portion of a texture (copyTexSubImage2D) should succeed with all bytes set to 0.");
|
||||
|
||||
var tex = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR);
|
||||
var fbo = gl.createFramebuffer();
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
|
||||
var rbo = gl.createRenderbuffer();
|
||||
gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
|
||||
var fboWidth = 16;
|
||||
var fboHeight = 16;
|
||||
gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, fboWidth, fboHeight);
|
||||
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo);
|
||||
shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
|
||||
gl.clearColor(1.0, 0.0, 0.0, 1.0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR);
|
||||
gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, width, height);
|
||||
checkNonZeroPixels(tex, width, height, 0, 0, fboWidth, fboHeight, 255, 0, 0, 255);
|
||||
gl.deleteTexture(tex);
|
||||
gl.finish();
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR);
|
||||
|
||||
debug("");
|
||||
debug("Reading an uninitialized portion of a texture (copyTexSubImage2D with negative x and y) should succeed with all bytes set to 0.");
|
||||
|
||||
var tex = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR);
|
||||
var fbo = gl.createFramebuffer();
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
|
||||
var rbo = gl.createRenderbuffer();
|
||||
gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
|
||||
var fboWidth = 16;
|
||||
var fboHeight = 16;
|
||||
gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, fboWidth, fboHeight);
|
||||
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo);
|
||||
shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
|
||||
gl.clearColor(1.0, 0.0, 0.0, 1.0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR);
|
||||
var x = -8;
|
||||
var y = -8;
|
||||
gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, x, y, width, height);
|
||||
checkNonZeroPixels(tex, width, height, -x, -y, fboWidth, fboHeight, 255, 0, 0, 255);
|
||||
gl.deleteTexture(tex);
|
||||
gl.finish();
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR);
|
||||
|
||||
debug("");
|
||||
debug("Reading an uninitialized portion of a texture (copyTexSubImage2D from WebGL internal fbo) should succeed with all bytes set to 0.");
|
||||
|
||||
var tex = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR);
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
gl.clearColor(0.0, 1.0, 0.0, 0.0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR);
|
||||
gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, width, height);
|
||||
checkNonZeroPixels(tex, width, height, 0, 0, canvas.width, canvas.height, 0, 255, 0, 0);
|
||||
gl.deleteTexture(tex);
|
||||
gl.finish();
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR);
|
||||
|
||||
//TODO: uninitialized vertex array buffer
|
||||
//TODO: uninitialized vertex elements buffer
|
||||
//TODO: uninitialized framebuffer? (implementations would need to do a GL clear at first binding?)
|
||||
|
@ -11,6 +11,10 @@ found in the LICENSE.txt file.
|
||||
<script type="application/javascript" src="../unit.js"></script>
|
||||
<script type="application/javascript" src="../util.js"></script>
|
||||
<script type="application/javascript" src="../../../js/webgl-test-utils.js"></script>
|
||||
</head><body>
|
||||
<canvas id="gl" width="16" height="16"></canvas>
|
||||
<canvas id="c" width="128" height="128"></canvas>
|
||||
<img id="i">
|
||||
<script type="application/javascript">
|
||||
var wtu = WebGLTestUtils;
|
||||
var defaultImgUrl = "https://get.webgl.org/conformance-resources/opengl_logo.jpg";
|
||||
@ -92,12 +96,18 @@ Tests.testReadPixelsSOPCanvas = function(gl) {
|
||||
}
|
||||
|
||||
Tests.endUnit = function(gl) {
|
||||
}
|
||||
};
|
||||
|
||||
wtu.setupImageForCrossOriginTest("#i", defaultImgUrl, localImgUrl, initTests);
|
||||
(async function() {
|
||||
const img = document.getElementById('i');
|
||||
try {
|
||||
await wtu.awaitOrTimeout(wtu.loadCrossOriginImage(img, defaultImgUrl, localImgUrl));
|
||||
} catch (e) {
|
||||
testFailed(`Image setup failed (${e}).`);
|
||||
finishTest();
|
||||
return;
|
||||
}
|
||||
initTests();
|
||||
})();
|
||||
</script>
|
||||
</head><body>
|
||||
<canvas id="gl" width="16" height="16"></canvas>
|
||||
<canvas id="c" width="128" height="128"></canvas>
|
||||
<img id="i">
|
||||
</body></html>
|
||||
|
@ -133,23 +133,14 @@ Tests.testTexImage2DNonSOP = function(gl) {
|
||||
Tests.endUnit = function(gl) {
|
||||
};
|
||||
|
||||
async function setupNonSOPImage() {
|
||||
const img = document.getElementById('i2');
|
||||
const url = wtu.chooseUrlForCrossOriginImage(defaultImgUrl, localImgUrl);
|
||||
img.src = url;
|
||||
await img.decode();
|
||||
}
|
||||
|
||||
async function throwOnTimeout(ms) {
|
||||
await wtu.awaitTimeout(ms);
|
||||
throw 'timeout';
|
||||
}
|
||||
|
||||
(async function() {
|
||||
const img = document.getElementById('i2');
|
||||
try {
|
||||
await Promise.race([setupNonSOPImage(), throwOnTimeout(1000)]);
|
||||
await wtu.awaitOrTimeout(wtu.loadCrossOriginImage(img, defaultImgUrl, localImgUrl));
|
||||
} catch (e) {
|
||||
console.log(`Image setup failed (${e}), running tests anyway.`);
|
||||
testFailed(`Image setup failed (${e}).`);
|
||||
finishTest();
|
||||
return;
|
||||
}
|
||||
initTests();
|
||||
})();
|
||||
|
@ -143,25 +143,16 @@ Tests.testTexImage2DNonSOP = function(gl) {
|
||||
}
|
||||
|
||||
Tests.endUnit = function(gl) {
|
||||
}
|
||||
|
||||
async function setupNonSOPImage() {
|
||||
const img = document.getElementById('i2');
|
||||
const url = wtu.chooseUrlForCrossOriginImage(defaultImgUrl, localImgUrl);
|
||||
img.src = url;
|
||||
await img.decode();
|
||||
}
|
||||
|
||||
async function throwOnTimeout(ms) {
|
||||
await wtu.awaitTimeout(ms);
|
||||
throw 'timeout';
|
||||
}
|
||||
};
|
||||
|
||||
(async function() {
|
||||
const img = document.getElementById('i2');
|
||||
try {
|
||||
await Promise.race([setupNonSOPImage(), throwOnTimeout(1000)]);
|
||||
await wtu.awaitOrTimeout(wtu.loadCrossOriginImage(img, defaultImgUrl, localImgUrl));
|
||||
} catch (e) {
|
||||
console.log(`Image setup failed (${e}), running tests anyway.`);
|
||||
testFailed(`Image setup failed (${e}).`);
|
||||
finishTest();
|
||||
return;
|
||||
}
|
||||
initTests();
|
||||
})();
|
||||
|
@ -33,7 +33,7 @@ function compareImages(refData, tstData, width, height, diff) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: Implement check that's used in OpenGL ES 2.0 conformance tests.
|
||||
// TODO: Implement crazy check that's used in OpenGL ES 2.0 conformance tests.
|
||||
// NOTE: on Desktop things seem to be working. Maybe the more complex check
|
||||
// is needed for embedded systems?
|
||||
return false;
|
||||
|
@ -24,6 +24,7 @@ found in the LICENSE.txt file.
|
||||
description("Checks that ReadPixels works as expected.");
|
||||
|
||||
var wtu = WebGLTestUtils;
|
||||
let gl;
|
||||
|
||||
debug("<h1>antialias = false</h1>")
|
||||
runTest(document.getElementById("example"), false);
|
||||
@ -35,7 +36,7 @@ var actual;
|
||||
var expected;
|
||||
|
||||
function runTest(canvas, antialias) {
|
||||
var gl = wtu.create3DContext(canvas, {antialias: antialias});
|
||||
gl = wtu.create3DContext(canvas, {antialias: antialias});
|
||||
var contextVersion = wtu.getDefault3DContextVersion();
|
||||
|
||||
var width = 2;
|
||||
@ -179,17 +180,10 @@ function runTest(canvas, antialias) {
|
||||
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),
|
||||
},
|
||||
|
||||
// -
|
||||
|
||||
const combinations = [
|
||||
{
|
||||
format: gl.RGB,
|
||||
type: gl.UNSIGNED_SHORT_5_6_5,
|
||||
@ -205,37 +199,113 @@ function runTest(canvas, antialias) {
|
||||
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([
|
||||
|
||||
const FORMATS = [
|
||||
{
|
||||
format: gl.RGBA,
|
||||
channels: 4,
|
||||
}, {
|
||||
format: gl.RGB,
|
||||
channels: 3,
|
||||
}, {
|
||||
format: gl.LUMINANCE_ALPHA,
|
||||
channels: 2,
|
||||
}, {
|
||||
format: gl.ALPHA,
|
||||
channels: 1,
|
||||
}, {
|
||||
format: gl.LUMINANCE,
|
||||
channels: 3,
|
||||
},
|
||||
];
|
||||
if (contextVersion >= 2) {
|
||||
FORMATS.push(
|
||||
{
|
||||
format: gl.RED,
|
||||
type: gl.UNSIGNED_BYTE,
|
||||
dest: new Uint8Array(1),
|
||||
},
|
||||
{
|
||||
channels: 1,
|
||||
}, {
|
||||
format: gl.RG,
|
||||
channels: 1,
|
||||
}, {
|
||||
format: gl.RGBA_INTEGER,
|
||||
type: gl.UNSIGNED_INT,
|
||||
dest: new Uint32Array(4),
|
||||
},
|
||||
{
|
||||
format: gl.RGBA_INTEGER,
|
||||
type: gl.INT,
|
||||
dest: new Int32Array(4),
|
||||
channels: 4,
|
||||
}, {
|
||||
format: gl.RGB_INTEGER,
|
||||
channels: 3,
|
||||
}, {
|
||||
format: gl.RG_INTEGER,
|
||||
channels: 2,
|
||||
}, {
|
||||
format: gl.RED_INTEGER,
|
||||
channels: 1,
|
||||
}
|
||||
]);
|
||||
);
|
||||
}
|
||||
|
||||
// -
|
||||
|
||||
const TYPES = [
|
||||
{
|
||||
type: gl.UNSIGNED_BYTE,
|
||||
ctor: Uint8Array,
|
||||
}, {
|
||||
type: gl.BYTE,
|
||||
ctor: Int8Array,
|
||||
}, {
|
||||
type: gl.UNSIGNED_SHORT,
|
||||
ctor: Uint16Array,
|
||||
}, {
|
||||
type: gl.SHORT,
|
||||
ctor: Int16Array,
|
||||
}, {
|
||||
type: gl.UNSIGNED_INT,
|
||||
ctor: Uint32Array,
|
||||
}, {
|
||||
type: gl.INT,
|
||||
ctor: Int32Array,
|
||||
}, {
|
||||
type: gl.FLOAT,
|
||||
ctor: Float32Array,
|
||||
}
|
||||
];
|
||||
|
||||
if (contextVersion >= 2) {
|
||||
TYPES.push(
|
||||
{
|
||||
type: gl.HALF_FLOAT,
|
||||
ctor: Uint16Array,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const ext = gl.getExtension('OES_texture_half_float');
|
||||
if (ext) {
|
||||
TYPES.push(
|
||||
{
|
||||
type: ext.HALF_FLOAT_OES,
|
||||
ctor: Uint16Array,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
for (const t of TYPES) {
|
||||
for (const f of FORMATS) {
|
||||
const desc = Object.assign({}, f, t);
|
||||
desc.dest = new desc.ctor(desc.channels);
|
||||
combinations.push(desc);
|
||||
}
|
||||
}
|
||||
|
||||
// -
|
||||
|
||||
debug("");
|
||||
debug("check invalid combinations of format/type");
|
||||
|
||||
var implFormat = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_FORMAT);
|
||||
var implType = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_TYPE);
|
||||
debug("IMPLEMENTATION_COLOR_READ_FORMAT: " + wtu.glEnumToString(gl, implFormat));
|
||||
debug("IMPLEMENTATION_COLOR_READ_TYPE: " + wtu.glEnumToString(gl, implType));
|
||||
|
||||
for (var tt = 0; tt < combinations.length; ++ tt) {
|
||||
var info = combinations[tt];
|
||||
@ -253,7 +323,7 @@ function runTest(canvas, antialias) {
|
||||
" / " + wtu.glEnumToString(gl, type));
|
||||
} else {
|
||||
wtu.glErrorShouldBe(
|
||||
gl, gl.INVALID_OPERATION,
|
||||
gl, [gl.INVALID_OPERATION, gl.INVALID_ENUM],
|
||||
"Should not be able to read as " + wtu.glEnumToString(gl, format) +
|
||||
" / " + wtu.glEnumToString(gl, type));
|
||||
}
|
||||
@ -335,6 +405,22 @@ function runTest(canvas, antialias) {
|
||||
"color pixel at 0, 0 should be [0, 255, 0, 255], was " +
|
||||
[buf[0], buf[1], buf[2], buf[3]]);
|
||||
}
|
||||
|
||||
const validDatas = [
|
||||
`new Uint8Array(4)`,
|
||||
`new Uint8Array(new ArrayBuffer(4))`,
|
||||
`new Uint8ClampedArray(4)`,
|
||||
`new Uint8ClampedArray(new ArrayBuffer(4))`,
|
||||
];
|
||||
if (window.SharedArrayBuffer) {
|
||||
validDatas.push(
|
||||
`new Uint8Array(new SharedArrayBuffer(4))`,
|
||||
`new Uint8ClampedArray(new SharedArrayBuffer(4))`
|
||||
);
|
||||
}
|
||||
for (const x of validDatas) {
|
||||
shouldNotThrow(`gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, ${x});`);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -4,12 +4,12 @@ Use of this source code is governed by an MIT-style license that can be
|
||||
found in the LICENSE.txt file.
|
||||
-->
|
||||
|
||||
<!--
|
||||
This bug would occur after the app would render several times with the
|
||||
same vertex attributes and buffers, but using a different start offset.
|
||||
One of the buffers would likely have to be DYNAMIC.
|
||||
|
||||
See http://anglebug.com/1327 and http://crbug.com/594509
|
||||
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
@ -126,6 +126,7 @@ function runTest()
|
||||
|
||||
debug('Polygon offset factor of 0.1 should alter order of slanted polygons');
|
||||
clear(gl, red, 1.0);
|
||||
gl.polygonOffset(0, 0);
|
||||
draw(gl, slantedSquare, colLoc, green);
|
||||
gl.polygonOffset(0.1, 0);
|
||||
draw(gl, slantedSquare, colLoc, blue);
|
||||
@ -133,6 +134,7 @@ function runTest()
|
||||
|
||||
debug('Polygon offset factor of 0.1 should not alter order of flat polygons');
|
||||
clear(gl, red, 1.0);
|
||||
gl.polygonOffset(0, 0);
|
||||
draw(gl, flatSquare, colLoc, blue);
|
||||
gl.polygonOffset(0.1, 0);
|
||||
draw(gl, flatSquare, colLoc, green);
|
||||
|
@ -1,3 +1,4 @@
|
||||
--min-version 1.0.4 fb-attach-implicit-target-assignment.html
|
||||
gl-enable-enum-test.html
|
||||
--max-version 1.9.9 gl-enum-tests.html
|
||||
gl-get-calls.html
|
||||
|
@ -0,0 +1,94 @@
|
||||
<!--
|
||||
Copyright (c) 2019 The Khronos Group Inc.
|
||||
Use of this source code is governed by an MIT-style license that can be
|
||||
found in the LICENSE.txt file.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<title>WebGL gl calls Conformance Tests</title>
|
||||
<link rel='stylesheet' href='../../resources/js-test-style.css'/>
|
||||
<script src='../../js/js-test-pre.js'></script>
|
||||
<script src='../../js/webgl-test-utils.js'></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id='description'></div>
|
||||
<div id='console'></div>
|
||||
<canvas id='canvas' width='2' height='2'> </canvas>
|
||||
<script>
|
||||
'use strict';
|
||||
description('Test implicit target assignment during FB attachment');
|
||||
|
||||
const wtu = WebGLTestUtils;
|
||||
const gl = wtu.create3DContext('canvas');
|
||||
let fb, rb, tex;
|
||||
|
||||
(() => {
|
||||
if (!gl) {
|
||||
testFailed('context does not exist');
|
||||
return;
|
||||
}
|
||||
|
||||
fb = gl.createFramebuffer();
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
|
||||
|
||||
wtu.glErrorShouldBe(gl, 0, 'No errors');
|
||||
|
||||
// -
|
||||
|
||||
debug('');
|
||||
debug('framebufferRenderbuffer');
|
||||
|
||||
rb = gl.createRenderbuffer();
|
||||
shouldBe('gl.isRenderbuffer(rb)', 'false');
|
||||
gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
|
||||
shouldBe('gl.isRenderbuffer(rb)', 'true');
|
||||
|
||||
rb = gl.createRenderbuffer();
|
||||
shouldBe('gl.isRenderbuffer(rb)', 'false');
|
||||
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, 'framebufferRenderbuffer must be preceeded by some bindRenderbuffer');
|
||||
shouldBe('gl.isRenderbuffer(rb)', 'false');
|
||||
|
||||
wtu.glErrorShouldBe(gl, 0, 'No errors');
|
||||
|
||||
// -
|
||||
|
||||
debug('');
|
||||
debug('framebufferTexture2D');
|
||||
|
||||
tex = gl.createTexture();
|
||||
shouldBe('gl.isTexture(tex)', 'false');
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex);
|
||||
shouldBe('gl.isTexture(tex)', 'true');
|
||||
|
||||
tex = gl.createTexture();
|
||||
shouldBe('gl.isTexture(tex)', 'false');
|
||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1636524 :
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, 'framebufferTexture2D must be preceeded by some bindTexture');
|
||||
shouldBe('gl.isTexture(tex)', 'false');
|
||||
|
||||
gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
|
||||
wtu.glErrorShouldBe(gl, 0, 'No errors after bindTexture');
|
||||
|
||||
tex = gl.createTexture();
|
||||
shouldBe('gl.isTexture(tex)', 'false');
|
||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X, tex, 0);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, 'framebufferTexture2D must be preceeded by some bindTexture');
|
||||
shouldBe('gl.isTexture(tex)', 'false');
|
||||
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex);
|
||||
wtu.glErrorShouldBe(gl, 0, 'No errors after bindTexture');
|
||||
})();
|
||||
|
||||
debug('');
|
||||
var successfullyParsed = true;
|
||||
|
||||
</script>
|
||||
<script src='../../js/js-test-post.js'></script>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,5 +1,5 @@
|
||||
--min-version 1.0.4 canvas-teximage-after-multiple-drawimages.html
|
||||
compressed-tex-image.html
|
||||
--max-version 1.9.9 compressed-tex-image.html
|
||||
copy-tex-image-and-sub-image-2d.html
|
||||
--min-version 1.0.2 copy-tex-image-2d-formats.html
|
||||
--min-version 1.0.4 copy-tex-image-crash.html
|
||||
@ -8,9 +8,11 @@ copy-tex-image-and-sub-image-2d.html
|
||||
--min-version 1.0.4 cube-incomplete-fbo.html
|
||||
--min-version 1.0.4 cube-map-uploads-out-of-order.html
|
||||
--min-version 1.0.3 default-texture.html
|
||||
--min-version 1.0.4 exif-orientation.html
|
||||
--min-version 1.0.2 --max-version 1.9.9 gl-get-tex-parameter.html
|
||||
gl-pixelstorei.html
|
||||
gl-teximage.html
|
||||
--min-version 1.0.2 mipmap-fbo.html
|
||||
origin-clean-conformance.html
|
||||
--min-version 1.0.4 origin-clean-conformance-offscreencanvas.html
|
||||
tex-image-and-sub-image-2d-with-array-buffer-view.html
|
||||
@ -29,11 +31,14 @@ texture-active-bind.html
|
||||
--min-version 1.0.2 texture-attachment-formats.html
|
||||
--min-version 1.0.2 texture-clear.html
|
||||
texture-complete.html
|
||||
--min-version 1.0.4 texture-copying-and-deletion.html
|
||||
--min-version 1.0.3 texture-copying-feedback-loops.html
|
||||
--min-version 1.0.4 texture-corner-case-videos.html
|
||||
--min-version 1.0.4 texture-cube-as-fbo-attachment.html
|
||||
--min-version 1.0.2 texture-hd-dpi.html
|
||||
--min-version 1.0.3 texture-draw-with-2d-and-cube.html
|
||||
--min-version 1.0.3 --max-version 1.9.9 texture-fakeblack.html
|
||||
--min-version 1.0.2 --max-version 1.9.9 texture-formats-test.html
|
||||
--min-version 1.0.2 texture-hd-dpi.html
|
||||
texture-mips.html
|
||||
--max-version 1.9.9 texture-npot-video.html
|
||||
--max-version 1.9.9 texture-npot.html
|
||||
@ -44,8 +49,8 @@ texture-size-cube-maps.html
|
||||
texture-transparent-pixels-initialized.html
|
||||
--min-version 1.0.2 texture-upload-cube-maps.html
|
||||
--min-version 1.0.3 texture-upload-size.html
|
||||
--min-version 1.0.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
|
||||
--min-version 1.0.4 upload-from-srcset-with-empty-data.html
|
||||
--min-version 1.0.4 video-rotation.html
|
||||
--min-version 1.0.4 png-image-types.html
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
Copyright (c) 2019 The Khronos Group Inc.
|
||||
Copyright (c) 2020 The Khronos Group Inc.
|
||||
Use of this source code is governed by an MIT-style license that can be
|
||||
found in the LICENSE.txt file.
|
||||
-->
|
||||
@ -8,8 +8,7 @@ found in the LICENSE.txt file.
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>WebGL compressed texture test</title>
|
||||
<LINK rel="stylesheet" href="../../../resources/js-test-style.css"/>
|
||||
<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
|
||||
<script src="../../../js/js-test-pre.js"></script>
|
||||
<script src="../../../js/webgl-test-utils.js"></script>
|
||||
</head>
|
||||
@ -17,100 +16,9 @@ found in the LICENSE.txt file.
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<script>
|
||||
"use strict";
|
||||
description("This test ensures WebGL implementations correctly implement querying for compressed textures when extensions are disabled.");
|
||||
|
||||
debug("");
|
||||
|
||||
const wtu = WebGLTestUtils;
|
||||
const gl = wtu.create3DContext();
|
||||
|
||||
const COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00;
|
||||
const COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02;
|
||||
|
||||
let formats = null;
|
||||
let ext;
|
||||
|
||||
if (!gl) {
|
||||
testFailed("context does not exist");
|
||||
} else {
|
||||
testPassed("context exists");
|
||||
|
||||
var tex = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex);
|
||||
wtu.shouldGenerateGLError(gl, [gl.INVALID_ENUM, gl.INVALID_OPERATION],
|
||||
"gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 10, 10, COMPRESSED_RGB_PVRTC_4BPPV1_IMG, new Uint8Array(8));");
|
||||
|
||||
wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_RGB_PVRTC_4BPPV1_IMG, 8, 8, 0, new Uint8Array(8))");
|
||||
wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, 8, 8, 0, new Uint8Array(8))");
|
||||
|
||||
wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "formats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS)");
|
||||
shouldBeNonNull("formats");
|
||||
shouldBe("formats.length", "0");
|
||||
|
||||
wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4*4*4));");
|
||||
wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM,
|
||||
"gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 4, 4, COMPRESSED_RGB_PVRTC_4BPPV1_IMG, new Uint8Array(8));");
|
||||
|
||||
// Check too-many and too-few args.
|
||||
|
||||
wtu.shouldThrow(gl, false, "too many args", function() {
|
||||
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_RGB_PVRTC_4BPPV1_IMG, 4, 4, 0, new Uint8Array(8), null);
|
||||
});
|
||||
wtu.shouldThrow(gl, TypeError, "too few args", function() {
|
||||
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_RGB_PVRTC_4BPPV1_IMG, 4, 4, 0);
|
||||
});
|
||||
|
||||
wtu.shouldThrow(gl, false, "too many args", function() {
|
||||
gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 4, 4, COMPRESSED_RGB_PVRTC_4BPPV1_IMG, new Uint8Array(8), null);
|
||||
});
|
||||
wtu.shouldThrow(gl, TypeError, "too few args", function() {
|
||||
gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 4, 4, COMPRESSED_RGB_PVRTC_4BPPV1_IMG);
|
||||
});
|
||||
|
||||
if (gl.PIXEL_UNPACK_BUFFER) {
|
||||
const buf = gl.createBuffer();
|
||||
gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, buf);
|
||||
const tex = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex);
|
||||
|
||||
function validateExt(extName, enumName, blockSize, blockByteSize) {
|
||||
ext = gl.getExtension(extName);
|
||||
if (!ext) {
|
||||
testPassed(`Optional ext ${extName} MAY be unsupported.`);
|
||||
return;
|
||||
}
|
||||
testPassed(`Optional ext ${extName} is supported.`);
|
||||
gl.bufferData(gl.PIXEL_UNPACK_BUFFER, blockByteSize*2, gl.STATIC_DRAW);
|
||||
|
||||
wtu.shouldGenerateGLError(gl, gl.NO_ERROR,
|
||||
`gl.compressedTexImage2D(gl.TEXTURE_2D, 0, ext.${enumName}, ${blockSize},${blockSize}, 0, ${blockByteSize}, 0)`);
|
||||
wtu.shouldGenerateGLError(gl, gl.NO_ERROR,
|
||||
`gl.compressedTexImage2D(gl.TEXTURE_2D, 0, ext.${enumName}, ${blockSize},${blockSize}, 0, ${blockByteSize}, 1)`);
|
||||
wtu.shouldGenerateGLError(gl, gl.NO_ERROR,
|
||||
`gl.compressedTexImage2D(gl.TEXTURE_2D, 0, ext.${enumName}, ${blockSize},${blockSize}, 0, ${blockByteSize}, ${blockByteSize})`);
|
||||
wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION,
|
||||
`gl.compressedTexImage2D(gl.TEXTURE_2D, 0, ext.${enumName}, ${blockSize},${blockSize}, 0, ${blockByteSize}, ${blockByteSize+1})`);
|
||||
|
||||
wtu.shouldGenerateGLError(gl, gl.NO_ERROR,
|
||||
`gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0,0, ${blockSize},${blockSize}, ext.${enumName}, ${blockByteSize}, 0)`);
|
||||
wtu.shouldGenerateGLError(gl, gl.NO_ERROR,
|
||||
`gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0,0, ${blockSize},${blockSize}, ext.${enumName}, ${blockByteSize}, 1)`);
|
||||
wtu.shouldGenerateGLError(gl, gl.NO_ERROR,
|
||||
`gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0,0, ${blockSize},${blockSize}, ext.${enumName}, ${blockByteSize}, ${blockByteSize})`);
|
||||
wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION,
|
||||
`gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0,0, ${blockSize},${blockSize}, ext.${enumName}, ${blockByteSize}, ${blockByteSize+1})`);
|
||||
}
|
||||
|
||||
validateExt('WEBGL_compressed_texture_s3tc', 'COMPRESSED_RGBA_S3TC_DXT5_EXT', 4, 16);
|
||||
validateExt('WEBGL_compressed_texture_etc1', 'COMPRESSED_RGB_ETC1_WEBGL', 4, 8);
|
||||
validateExt('WEBGL_compressed_texture_etc', 'COMPRESSED_RGBA8_ETC2_EAC', 4, 16);
|
||||
validateExt('WEBGL_compressed_texture_astc', 'COMPRESSED_RGBA_ASTC_4x4_KHR', 4, 16);
|
||||
}
|
||||
}
|
||||
|
||||
var successfullyParsed = true;
|
||||
const contextVersion = 1;
|
||||
</script>
|
||||
<script src="../../../js/tests/compressed-tex-image.js"></script>
|
||||
<script src="../../../js/js-test-post.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -0,0 +1,167 @@
|
||||
<!--
|
||||
Copyright (c) 2020 The Khronos Group Inc.
|
||||
Use of this source code is governed by an MIT-style license that can be
|
||||
found in the LICENSE.txt file.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Verifies EXIF orientation is respected when uploading images to WebGL textures</title>
|
||||
<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
|
||||
<script src="../../../js/js-test-pre.js"></script>
|
||||
<script src="../../../js/webgl-test-utils.js"></script>
|
||||
<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
|
||||
</head>
|
||||
<body onload="run()">
|
||||
<canvas id="c" width="256" height="256"></canvas>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<script>
|
||||
"use strict";
|
||||
description();
|
||||
let wtu = WebGLTestUtils;
|
||||
let tiu = TexImageUtils;
|
||||
let canvas = document.getElementById("c");
|
||||
let gl = wtu.create3DContext(canvas);
|
||||
let program = tiu.setupTexturedQuad(gl, gl.RGBA);
|
||||
const resourcePath = "../../../resources/";
|
||||
const tolerance = 5;
|
||||
|
||||
// The locations are written assuming flipY = false. For flipY = true, y = 1.0-y.
|
||||
const expectedColors = {
|
||||
top: { location: [ 0.5, 0.25 ], color: [ 255, 0, 0 ] },
|
||||
left: { location: [ 0.4, 0.5 ], color: [ 0, 0, 255 ] },
|
||||
right: { location: [ 0.6, 0.5 ], color: [ 255, 255, 0 ] },
|
||||
bottom: { location: [ 0.5, 0.75 ], color: [ 0, 255, 0 ] },
|
||||
}
|
||||
|
||||
function output(str)
|
||||
{
|
||||
debug(str);
|
||||
bufferedLogToConsole(str);
|
||||
}
|
||||
|
||||
function checkPixels(flipY)
|
||||
{
|
||||
for (let place in expectedColors) {
|
||||
let color = expectedColors[place];
|
||||
let loc = color.location;
|
||||
let x = loc[0];
|
||||
let y = (flipY ? 1.0 - loc[1] : loc[1]);
|
||||
output(" Checking " + place);
|
||||
wtu.checkCanvasRect(gl, Math.floor(canvas.width * x), Math.floor(canvas.height * y), 1, 1,
|
||||
color.color, "shouldBe " + color.color + " +/-" + tolerance, tolerance);
|
||||
}
|
||||
}
|
||||
|
||||
async function testImageBitmapFromBlobWithFlipY(blob, flipY)
|
||||
{
|
||||
let bitmap;
|
||||
// As a concession to Firefox, which doesn't yet implement
|
||||
// createImageBitmap with creation options, skip the tests
|
||||
// involving flipY=true if ImageBitmap creation throws an
|
||||
// exception, and use the single-argument constructor for the
|
||||
// flipY=false case.
|
||||
if (flipY) {
|
||||
try {
|
||||
bitmap = await createImageBitmap(blob, {imageOrientation: flipY});
|
||||
} catch (e) {
|
||||
output(" (createImageBitmap options not supported - skipping flipY=true case)");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
bitmap = await createImageBitmap(blob);
|
||||
}
|
||||
|
||||
output(" Testing texImage2D, flipY = " + flipY);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, bitmap);
|
||||
wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
|
||||
checkPixels(flipY);
|
||||
|
||||
output(" Testing texSubImage2D, flipY = " + flipY);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, bitmap.width, bitmap.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
||||
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, bitmap);
|
||||
wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
|
||||
checkPixels(flipY);
|
||||
}
|
||||
|
||||
async function testImageBitmapFromBlob(filename)
|
||||
{
|
||||
let response = await fetch(resourcePath + filename);
|
||||
let blob = await response.blob();
|
||||
output("----------------------------------------------------------------");
|
||||
output("Testing " + filename + " via ImageBitmap from Blob");
|
||||
await testImageBitmapFromBlobWithFlipY(blob, true);
|
||||
await testImageBitmapFromBlobWithFlipY(blob, false);
|
||||
}
|
||||
|
||||
async function testImageElementWithFlipY(image, flipY)
|
||||
{
|
||||
output(" Testing texImage2D, flipY = " + flipY);
|
||||
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
|
||||
wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
|
||||
checkPixels(flipY);
|
||||
|
||||
output(" Testing texSubImage2D, flipY = " + flipY);
|
||||
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, image.width, image.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
||||
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, image);
|
||||
wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
|
||||
checkPixels(flipY);
|
||||
}
|
||||
|
||||
async function testImageElement(filename)
|
||||
{
|
||||
let image = new Image();
|
||||
image.src = resourcePath + filename;
|
||||
await image.decode();
|
||||
|
||||
output("----------------------------------------------------------------");
|
||||
output("Testing " + filename + " via HTMLImageElement");
|
||||
|
||||
await testImageElementWithFlipY(image, true);
|
||||
await testImageElementWithFlipY(image, false);
|
||||
}
|
||||
|
||||
async function testSingleImage(filename)
|
||||
{
|
||||
await testImageBitmapFromBlob(filename);
|
||||
await testImageElement(filename);
|
||||
}
|
||||
|
||||
async function run()
|
||||
{
|
||||
let tex = gl.createTexture();
|
||||
// Bind the texture to the default texture unit 0
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex);
|
||||
// Set up texture parameters
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
|
||||
const filenames = [
|
||||
"exif-orientation-test-1-normal.jpg",
|
||||
"exif-orientation-test-2-mirror-horizontal.jpg",
|
||||
"exif-orientation-test-3-rotate-180.jpg",
|
||||
"exif-orientation-test-4-mirror-vertical.jpg",
|
||||
"exif-orientation-test-5-mirror-horizontal-90-ccw.jpg",
|
||||
"exif-orientation-test-6-90-ccw.jpg",
|
||||
"exif-orientation-test-7-mirror-horizontal-90-cw.jpg",
|
||||
"exif-orientation-test-8-90-cw.jpg",
|
||||
];
|
||||
|
||||
for (let fn of filenames) {
|
||||
await testSingleImage(fn);
|
||||
}
|
||||
|
||||
finishTest();
|
||||
}
|
||||
|
||||
var successfullyParsed = true;
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -12,6 +12,12 @@ found in the LICENSE.txt file.
|
||||
<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
|
||||
<script src="../../../js/js-test-pre.js"></script>
|
||||
<script src="../../../js/webgl-test-utils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<canvas id="canvas"></canvas>
|
||||
<img id="img" style="display:none;">
|
||||
<script>
|
||||
"use strict";
|
||||
var wtu = WebGLTestUtils;
|
||||
@ -33,7 +39,7 @@ var localImgUrl = "../../../resources/opengl_logo.jpg";
|
||||
var imgDomain;
|
||||
var pageDomain;
|
||||
|
||||
function imageLoaded() {
|
||||
function imageLoaded(img) {
|
||||
description("This test ensures WebGL implementations for OffscreenCanvas follow proper same-origin restrictions.");
|
||||
|
||||
if (!window.OffscreenCanvas) {
|
||||
@ -42,8 +48,6 @@ function imageLoaded() {
|
||||
return;
|
||||
}
|
||||
|
||||
var img = this;
|
||||
|
||||
assertMsg(img.width > 0 && img.height > 0, "img was loaded");
|
||||
imgDomain = wtu.getBaseDomain(wtu.getHost(img.src));
|
||||
pageDomain = wtu.getBaseDomain(window.location.host);
|
||||
@ -105,13 +109,17 @@ function imageLoaded() {
|
||||
finishTest();
|
||||
}
|
||||
|
||||
wtu.setupImageForCrossOriginTest("#img", defaultImgUrl, localImgUrl, imageLoaded);
|
||||
(async function() {
|
||||
const img = document.getElementById('img');
|
||||
try {
|
||||
await wtu.awaitOrTimeout(wtu.loadCrossOriginImage(img, defaultImgUrl, localImgUrl));
|
||||
} catch (e) {
|
||||
testFailed(`Image setup failed (${e}).`);
|
||||
finishTest();
|
||||
return;
|
||||
}
|
||||
imageLoaded(img);
|
||||
})();
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<canvas id="canvas"></canvas>
|
||||
<img id="img" style="display:none;">
|
||||
</body>
|
||||
</html>
|
||||
|
@ -12,6 +12,13 @@ found in the LICENSE.txt file.
|
||||
<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
|
||||
<script src="../../../js/js-test-pre.js"></script>
|
||||
<script src="../../../js/webgl-test-utils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<canvas id="canvas1"></canvas>
|
||||
<canvas id="canvas2"></canvas>
|
||||
<img id="img" style="display:none;">
|
||||
<script>
|
||||
"use strict";
|
||||
var wtu = WebGLTestUtils;
|
||||
@ -34,9 +41,8 @@ var imgDomain;
|
||||
var pageDomain;
|
||||
var successfullyParsed;
|
||||
|
||||
function imageLoaded() {
|
||||
function imageLoaded(img) {
|
||||
description("This test ensures WebGL implementations follow proper same-origin restrictions.");
|
||||
var img = this;
|
||||
|
||||
assertMsg(img.width > 0 && img.height > 0, "img was loaded");
|
||||
imgDomain = wtu.getBaseDomain(wtu.getHost(img.src));
|
||||
@ -115,14 +121,17 @@ function imageLoaded() {
|
||||
notifyFinishedToHarness();
|
||||
}
|
||||
|
||||
wtu.setupImageForCrossOriginTest("#img", defaultImgUrl, localImgUrl, imageLoaded);
|
||||
(async function() {
|
||||
const img = document.getElementById('img');
|
||||
try {
|
||||
await wtu.awaitOrTimeout(wtu.loadCrossOriginImage(img, defaultImgUrl, localImgUrl));
|
||||
} catch (e) {
|
||||
testFailed(`Image setup failed (${e}).`);
|
||||
finishTest();
|
||||
return;
|
||||
}
|
||||
imageLoaded(img);
|
||||
})();
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<canvas id="canvas1"></canvas>
|
||||
<canvas id="canvas2"></canvas>
|
||||
<img id="img" style="display:none;">
|
||||
</body>
|
||||
</html>
|
||||
|
@ -0,0 +1,164 @@
|
||||
<!--
|
||||
Copyright (c) 2021 The Khronos Group Inc.
|
||||
Use of this source code is governed by an MIT-style license that can be
|
||||
found in the LICENSE.txt file.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="../../../resources/js-test-style.css" />
|
||||
<script src="../../../js/js-test-pre.js"></script>
|
||||
<script src="../../../js/webgl-test-utils.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<script>
|
||||
"use strict";
|
||||
description("This test verifies correct channel mapping of different PNG image types.");
|
||||
|
||||
const testData = {
|
||||
"Grayscale": {
|
||||
src: [
|
||||
// [0x40]
|
||||
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVAAAACklEQVQI12NwAAAAQgBBg7nsrQAAAABJRU5ErkJggg==",
|
||||
// [0x4040]
|
||||
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABEAAAAABq7kcWAAAAC0lEQVQI12NwcAAAAMMAgUenLEIAAAAASUVORK5CYII="
|
||||
],
|
||||
expectations: [
|
||||
{ color: [0x00, 0x00, 0x00, 0xFF], format: "ALPHA" },
|
||||
{ color: [0x40, 0x40, 0x40, 0xFF], format: "RGB" },
|
||||
{ color: [0x40, 0x40, 0x40, 0xFF], format: "RGBA" },
|
||||
{ color: [0x40, 0x40, 0x40, 0xFF], format: "LUMINANCE" },
|
||||
{ color: [0x40, 0x40, 0x40, 0xFF], format: "LUMINANCE_ALPHA" },
|
||||
{ color: [0x40, 0x00, 0x00, 0xFF], format: "RED", internalformat: "R8" },
|
||||
{ color: [0x40, 0x40, 0x00, 0xFF], format: "RG", internalformat: "RG8" }
|
||||
]
|
||||
},
|
||||
"Grayscale Alpha": {
|
||||
src: [
|
||||
// [0x40, 0x80]
|
||||
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQI12NwaAAAAQMAwUxZTl4AAAAASUVORK5CYII=",
|
||||
// [0x4040, 0x8080]
|
||||
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABEAQAAADljNBBAAAADUlEQVQI12NwcGhoAAADRQGBoxssPgAAAABJRU5ErkJggg=="
|
||||
],
|
||||
expectations: [
|
||||
{ color: [0x00, 0x00, 0x00, 0x80], format: "ALPHA" },
|
||||
{ color: [0x40, 0x40, 0x40, 0xFF], format: "RGB" },
|
||||
{ color: [0x40, 0x40, 0x40, 0x80], format: "RGBA" },
|
||||
{ color: [0x40, 0x40, 0x40, 0xFF], format: "LUMINANCE" },
|
||||
{ color: [0x40, 0x40, 0x40, 0x80], format: "LUMINANCE_ALPHA" },
|
||||
{ color: [0x40, 0x00, 0x00, 0xFF], format: "RED", internalformat: "R8" },
|
||||
{ color: [0x40, 0x40, 0x00, 0xFF], format: "RG", internalformat: "RG8" }
|
||||
]
|
||||
},
|
||||
"Color": {
|
||||
src: [
|
||||
// [0xBF, 0x7F, 0xFF]
|
||||
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVQI12PYX/8fAAQ+Aj5BqwprAAAAAElFTkSuQmCC",
|
||||
// [0xBFBF, 0x7F7F, 0xFFFF]
|
||||
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABEAIAAADA54+dAAAAD0lEQVQI12PYv7++/v9/AA6yBHvtbgBNAAAAAElFTkSuQmCC"
|
||||
],
|
||||
expectations: [
|
||||
{ color: [0x00, 0x00, 0x00, 0xFF], format: "ALPHA" },
|
||||
{ color: [0xBF, 0x7F, 0xFF, 0xFF], format: "RGB" },
|
||||
{ color: [0xBF, 0x7F, 0xFF, 0xFF], format: "RGBA" },
|
||||
{ color: [0xBF, 0xBF, 0xBF, 0xFF], format: "LUMINANCE" },
|
||||
{ color: [0xBF, 0xBF, 0xBF, 0xFF], format: "LUMINANCE_ALPHA" },
|
||||
{ color: [0xBF, 0x00, 0x00, 0xFF], format: "RED", internalformat: "R8" },
|
||||
{ color: [0xBF, 0x7F, 0x00, 0xFF], format: "RG", internalformat: "RG8" }
|
||||
]
|
||||
|
||||
},
|
||||
"Color Alpha": {
|
||||
src: [
|
||||
// [0xBF, 0x7F, 0xFF, 0x40]
|
||||
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQI12PYX//fAQAGvAJ+xPMwKQAAAABJRU5ErkJggg==",
|
||||
// [0xBFBF, 0x7F7F, 0xFFFF, 0x4040]
|
||||
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABEAYAAABPhRjKAAAAEUlEQVQI12PYv7++/v9/BwcAGGgE+8YN4XUAAAAASUVORK5CYII="
|
||||
],
|
||||
expectations: [
|
||||
{ color: [0x00, 0x00, 0x00, 0x40], format: "ALPHA" },
|
||||
{ color: [0xBF, 0x7F, 0xFF, 0xFF], format: "RGB" },
|
||||
{ color: [0xBF, 0x7F, 0xFF, 0x40], format: "RGBA" },
|
||||
{ color: [0xBF, 0xBF, 0xBF, 0xFF], format: "LUMINANCE" },
|
||||
{ color: [0xBF, 0xBF, 0xBF, 0x40], format: "LUMINANCE_ALPHA" },
|
||||
{ color: [0xBF, 0x00, 0x00, 0xFF], format: "RED", internalformat: "R8" },
|
||||
{ color: [0xBF, 0x7F, 0x00, 0xFF], format: "RG", internalformat: "RG8" }
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
const wtu = WebGLTestUtils;
|
||||
const gl = wtu.create3DContext();
|
||||
|
||||
wtu.setupTexturedQuad(gl);
|
||||
gl.bindTexture(gl.TEXTURE_2D, gl.createTexture());
|
||||
|
||||
(async () => {
|
||||
for (const [type, testCase] of Object.entries(testData)) {
|
||||
if (testCase.src.length != 2) throw new Error('testCase.src.length != 2');
|
||||
let images = testCase.src.map(src => loadImage(src));
|
||||
images = await Promise.all(images);
|
||||
debug("");
|
||||
debug("");
|
||||
debug(`PNG image type ${type} with RGBA values of ${testCase.expectations[2].color}`);
|
||||
let formats = testCase.expectations;
|
||||
if (!wtu.isWebGL2(gl)) {
|
||||
formats = formats.filter((f) => !f.internalformat);
|
||||
}
|
||||
for (const f of formats) {
|
||||
debug("");
|
||||
debug(`GL format: ${f.format}`);
|
||||
|
||||
function check(data, description) {
|
||||
debug(`Upload ${description}`);
|
||||
gl.texImage2D(
|
||||
gl.TEXTURE_2D,
|
||||
0,
|
||||
gl[f.internalformat || f.format],
|
||||
gl[f.format],
|
||||
gl.UNSIGNED_BYTE,
|
||||
data
|
||||
);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR);
|
||||
wtu.clearAndDrawUnitQuad(gl);
|
||||
wtu.checkCanvas(gl, f.color, undefined, 1);
|
||||
}
|
||||
|
||||
check(images[0].image, "8-bit PNG from Image");
|
||||
check(images[1].image, "16-bit PNG from Image");
|
||||
|
||||
if (images[0].bitmap) {
|
||||
check(images[0].bitmap, "8-bit PNG from ImageBitmap");
|
||||
check(images[1].bitmap, "16-bit PNG from ImageBitmap");
|
||||
}
|
||||
}
|
||||
}
|
||||
finishTest();
|
||||
})();
|
||||
|
||||
async function loadImage(src) {
|
||||
const img = new Image();
|
||||
img.src = src;
|
||||
await img.decode();
|
||||
const ret = { image: img };
|
||||
if (self.createImageBitmap) {
|
||||
try {
|
||||
ret.bitmap = await createImageBitmap(img, {
|
||||
premultiplyAlpha: "none",
|
||||
});
|
||||
} catch {}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
var successfullyParsed = true;
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -264,7 +264,6 @@ function runTest(bindingTarget, program)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var gl = wtu.create3DContext("example");
|
||||
@ -275,6 +274,29 @@ program = wtu.setupTexturedQuadWithCubeMap(gl);
|
||||
runTest(gl.TEXTURE_CUBE_MAP, program);
|
||||
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
|
||||
|
||||
const tex = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex);
|
||||
|
||||
const validDatas = [
|
||||
`new Uint8Array(4)`,
|
||||
`new Uint8Array(new ArrayBuffer(4))`,
|
||||
`new Uint8ClampedArray(4)`,
|
||||
`new Uint8ClampedArray(new ArrayBuffer(4))`,
|
||||
];
|
||||
if (window.SharedArrayBuffer) {
|
||||
validDatas.push(
|
||||
`new Uint8Array(new SharedArrayBuffer(4))`,
|
||||
`new Uint8ClampedArray(new SharedArrayBuffer(4))`
|
||||
);
|
||||
}
|
||||
for (const x of validDatas) {
|
||||
shouldNotThrow(`gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1,1, 0, gl.RGBA, gl.UNSIGNED_BYTE, ${x});`);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
|
||||
shouldNotThrow(`gl.texSubImage2D(gl.TEXTURE_2D, 0, 0,0, 1,1, gl.RGBA, gl.UNSIGNED_BYTE, ${x});`);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
|
||||
}
|
||||
|
||||
var successfullyParsed = true;
|
||||
</script>
|
||||
<script src="../../../js/js-test-post.js"></script>
|
||||
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,91 @@
|
||||
<!--
|
||||
Copyright (c) 2020 The Khronos Group Inc.
|
||||
Use of this source code is governed by an MIT-style license that can be
|
||||
found in the LICENSE.txt file.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>WebGL Texture Copying and Deletion Test</title>
|
||||
<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
|
||||
<script src="../../../js/js-test-pre.js"></script>
|
||||
<script src="../../../js/webgl-test-utils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="example" width="1" height="1" style="width: 40px; height: 40px;"></canvas>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
description('Checks that texture copying and deletion work correctly together.');
|
||||
debug('Regression test for <a href="http://anglebug.com/4267">http://anglebug.com/4267</a>');
|
||||
const wtu = WebGLTestUtils;
|
||||
const canvas = document.getElementById("example");
|
||||
canvas.addEventListener('webglcontextlost', contextLost, false);
|
||||
|
||||
let contextWasLost = false;
|
||||
function contextLost(e) {
|
||||
e.preventDefault();
|
||||
contextWasLost = true;
|
||||
debug("***context lost -- should not happen***");
|
||||
}
|
||||
|
||||
const gl = wtu.create3DContext(canvas);
|
||||
|
||||
const texture = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
|
||||
const texture2 = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture2);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
|
||||
const framebuffer = gl.createFramebuffer();
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
|
||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
|
||||
assertMsg(gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE,
|
||||
"framebuffer should be FRAMEBUFFER_COMPLETE.");
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after setup");
|
||||
|
||||
// This test does not call getError, because doing so seems to cause
|
||||
// an implicit flush which intermittently masks the bug.
|
||||
|
||||
debug("");
|
||||
debug("testing copyTexImage2D");
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture);
|
||||
gl.copyTexImage2D(gl.TEXTURE_2D, 1, gl.RGBA, 0, 0, 2, 2, 0);
|
||||
// Not necessary to do any CopyTexImage2D operations to texture2.
|
||||
|
||||
debug("");
|
||||
debug("testing copyTexSubImage2D");
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture);
|
||||
gl.copyTexSubImage2D(gl.TEXTURE_2D, 1, 0, 0, 0, 0, 1, 1);
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture2);
|
||||
gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
|
||||
|
||||
debug('deleting framebuffer');
|
||||
gl.deleteFramebuffer(framebuffer);
|
||||
debug('deleting texture');
|
||||
gl.deleteTexture(texture);
|
||||
debug('deleting texture2');
|
||||
// On buggy driver, crashes during this deleteTexture call.
|
||||
gl.deleteTexture(texture2);
|
||||
|
||||
setTimeout(function() {
|
||||
shouldBe("contextWasLost", "false");
|
||||
finishTest();
|
||||
}, 1000);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -99,31 +99,33 @@ function runOneIteration(videoElement, useTexSubImage2D)
|
||||
// - Left is green and right is transparent-blended-with-red
|
||||
let leftIsGreen = false, leftIsRed = false, rightIsBlue = false, rightIsRed = false;
|
||||
let greenRedError = "", redBlueError = "";
|
||||
let leftGreenError = "", rightBlueError = "";
|
||||
let bufLeft, bufRight;
|
||||
wtu.checkCanvasRectColor(gl, 4, 4, 8, 24, green, tolerance,
|
||||
/* sameFn */ () => { leftIsGreen = true; }, /* differentFn */ m => {}, debug);
|
||||
/* sameFn */ () => { leftIsGreen = true; }, /* differentFn */ (m, b) => { leftGreenError = m; bufLeft = b;}, debug);
|
||||
wtu.checkCanvasRectColor(gl, 20, 4, 8, 24, red, tolerance,
|
||||
/* sameFn */ () => { rightIsRed = true; }, /* differentFn */ m => { greenRedError = m; }, debug);
|
||||
/* sameFn */ () => { rightIsRed = true; }, /* differentFn */ (m, b) => { greenRedError = m; bufRight = b;}, debug);
|
||||
|
||||
// - Right is blue and left is transparent-blended-with-red
|
||||
wtu.checkCanvasRectColor(gl, 20, 4, 8, 24, blue, tolerance,
|
||||
/* sameFn */ () => { rightIsBlue = true; }, /* differentFn */ m => {}, debug);
|
||||
/* sameFn */ () => { rightIsBlue = true; }, /* differentFn */ (m, b) => { rightBlueError = m; bufRight = b;}, debug);
|
||||
wtu.checkCanvasRectColor(gl, 4, 4, 8, 24, red, tolerance,
|
||||
/* sameFn */ () => { leftIsRed = true; }, /* differentFn */ m => { redBlueError = m; }, debug);
|
||||
/* sameFn */ () => { leftIsRed = true; }, /* differentFn */ (m, b) => { redBlueError = m; bufLeft = b;}, debug);
|
||||
|
||||
if (leftIsGreen) {
|
||||
if (rightIsRed) {
|
||||
testPassed("left is green, right is transparent-blended-with-red")
|
||||
testPassed("left is green, right is transparent-blended-with-red");
|
||||
} else {
|
||||
testFailed("left is green, but: " + greenRedError);
|
||||
testFailed("left is green, but: " + greenRedError + "\n" + bufRight);
|
||||
}
|
||||
} else if (rightIsBlue) {
|
||||
if (leftIsRed) {
|
||||
testPassed("right is blue, left is transparent-blended-with-red");
|
||||
} else {
|
||||
testFailed("right is blue, but: " + redBlueError);
|
||||
testFailed("right is blue, but: " + redBlueError + "\n" + bufLeft);
|
||||
}
|
||||
} else {
|
||||
testFailed("neither left is green nor right is blue")
|
||||
testFailed("neither left is green nor right is blue \n" + leftGreenError + "\n" + rightBlueError + "\n" + bufLeft + "\n" + bufRight);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -0,0 +1,44 @@
|
||||
<!--
|
||||
Copyright (c) 2020 The Khronos Group Inc.
|
||||
Use of this source code is governed by an MIT-style license that can be
|
||||
found in the LICENSE.txt file.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
|
||||
<title>Upload From Srcset With Empty Data</title>
|
||||
<script src="../../../js/js-test-pre.js"></script>
|
||||
<script src="../../../js/webgl-test-utils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<img srcset="data:,a 1x, data:,b 1w" id="i">
|
||||
<script>
|
||||
"use strict";
|
||||
var wtu = WebGLTestUtils;
|
||||
|
||||
var successfullyParsed;
|
||||
|
||||
description("This test ensures WebGL implementations handle srcsets with empty data.");
|
||||
debug("Regression test for <a href='http://crbug.com/1085044'>http://crbug.com/1085044</a>");
|
||||
|
||||
let gl = wtu.create3DContext();
|
||||
|
||||
// Note we run this test synchronously, rather than running it in an async
|
||||
// function called after "wtu.awaitOrTimeout(img.decode());". This reproduces
|
||||
// the bug more reliably.
|
||||
let img = document.getElementById("i");
|
||||
let tex = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex);
|
||||
// Implementations can decide how to respond to these kinds of bad
|
||||
// inputs, as long as they don't crash.
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
|
||||
|
||||
finishTest();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,167 @@
|
||||
<!--
|
||||
Copyright (c) 2021 The Khronos Group Inc.
|
||||
Use of this source code is governed by an MIT-style license that can be
|
||||
found in the LICENSE.txt file.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Verifies rotation metadata tag is respected when uploading videos to WebGL textures.</title>
|
||||
<link rel="stylesheet" href="../../../resources/js-test-style.css" />
|
||||
<script src="../../../js/js-test-pre.js"></script>
|
||||
<script src="../../../js/webgl-test-utils.js"></script>
|
||||
<script src="../../../js/tests/tex-image-and-sub-image-utils.js"></script>
|
||||
</head>
|
||||
|
||||
<body onload="run()">
|
||||
<canvas id="c" width="256" height="256"></canvas>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<script>
|
||||
"use strict";
|
||||
description();
|
||||
let wtu = WebGLTestUtils;
|
||||
let tiu = TexImageUtils;
|
||||
let canvas = document.getElementById("c");
|
||||
let gl = wtu.create3DContext(canvas);
|
||||
let program = tiu.setupTexturedQuad(gl, gl.RGBA);
|
||||
const resourcePath = "../../../resources/";
|
||||
const mp4Tolerance = 10;
|
||||
// Significantly higher tolerance needed for VP9 tests. http://crbug.com/1219015 .
|
||||
const vp9Tolerance = 45;
|
||||
|
||||
const expectedColors = {
|
||||
top: { location: [0.5, 0.25], color: [255, 0, 0] },
|
||||
left: { location: [0.4, 0.5], color: [0, 0, 255] },
|
||||
right: { location: [0.6, 0.5], color: [255, 255, 0] },
|
||||
bottom: { location: [0.5, 0.75], color: [0, 255, 0] },
|
||||
}
|
||||
|
||||
function output(str) {
|
||||
debug(str);
|
||||
bufferedLogToConsole(str);
|
||||
}
|
||||
|
||||
function checkPixels(tolerance) {
|
||||
for (let place in expectedColors) {
|
||||
let color = expectedColors[place];
|
||||
let loc = color.location;
|
||||
let x = loc[0];
|
||||
let y = loc[1];
|
||||
output(" Checking " + place);
|
||||
wtu.checkCanvasRect(gl, Math.floor(canvas.width * x), Math.floor(canvas.height * y), 1, 1,
|
||||
color.color, "shouldBe " + color.color + " +/-" + tolerance, tolerance);
|
||||
}
|
||||
}
|
||||
|
||||
function loadVideoElement(filename) {
|
||||
return new Promise((resolve) => {
|
||||
const video = document.createElement('video');
|
||||
video.crossOrigin = 'anonymous';
|
||||
video.src = resourcePath + filename;
|
||||
wtu.startPlayingAndWaitForVideo(video, resolve);
|
||||
});
|
||||
}
|
||||
|
||||
async function testVideoElement(filename, isVP9) {
|
||||
const video = await loadVideoElement(filename);
|
||||
|
||||
output("----------------------------------------------------------------");
|
||||
output("Testing " + filename + " via HTMLVideoElement");
|
||||
|
||||
output(" Testing texImage2D");
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, video);
|
||||
wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
|
||||
const localTolerance = isVP9 ? vp9Tolerance : mp4Tolerance;
|
||||
checkPixels(localTolerance);
|
||||
|
||||
output(" Testing texSubImage2D");
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, video.videoWidth, video.videoHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
||||
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, video);
|
||||
wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
|
||||
checkPixels(localTolerance);
|
||||
}
|
||||
|
||||
async function run() {
|
||||
await (async () => {
|
||||
const video = document.createElement('video');
|
||||
if (!video.canPlayType) {
|
||||
testFailed("video.canPlayType required method missing");
|
||||
return;
|
||||
}
|
||||
|
||||
let supports_h264 = !!video.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/no/, '');
|
||||
let supports_vp9 = !!video.canPlayType('video/mp4; codecs="vp09.00.10.08"').replace(/no/, '');
|
||||
if (!supports_h264 && !supports_vp9) {
|
||||
testFailed("No supported video types.");
|
||||
return;
|
||||
}
|
||||
|
||||
let tex = gl.createTexture();
|
||||
// Bind the texture to the default texture unit 0
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex);
|
||||
// Set up texture parameters
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
|
||||
// These files were created by converting exif-orientation-test.psd to mp4
|
||||
// files, rotating them using the transpose filter, and adding rotate metadata, all
|
||||
// using the ffmpeg command-line tool.
|
||||
//
|
||||
// From sdk/tests/resources/ directory:
|
||||
//
|
||||
// 0:
|
||||
// ffmpeg -noautorotate -i exif-orientation-originals\exif-orientation-test.psd -vf scale=128x96 -pix_fmt yuv420p -y temp.mp4
|
||||
// ffmpeg -i temp.mp4 -c copy -metadata:s:v:0 rotate=0 video-rotation-0.mp4
|
||||
// ffmpeg -noautorotate -i exif-orientation-originals\exif-orientation-test.psd -vf scale=128x96 -pix_fmt yuv420p -crf 0 -vcodec libvpx-vp9 -y temp.mp4
|
||||
// ffmpeg -i temp.mp4 -c copy -metadata:s:v:0 rotate=0 video-rotation-0.vp9.mp4
|
||||
//
|
||||
// 90:
|
||||
// ffmpeg -noautorotate -i exif-orientation-originals\exif-orientation-test.psd -vf scale=128x96,transpose=2 -pix_fmt yuv420p -y temp.mp4
|
||||
// ffmpeg -i temp.mp4 -c copy -metadata:s:v:0 rotate=270 video-rotation-90.mp4
|
||||
// ffmpeg -noautorotate -i exif-orientation-originals\exif-orientation-test.psd -vf scale=128x96,transpose=2 -pix_fmt yuv420p -crf 0 -vcodec libvpx-vp9 -y temp.mp4
|
||||
// ffmpeg -i temp.mp4 -c copy -metadata:s:v:0 rotate=270 video-rotation-90.vp9.mp4
|
||||
//
|
||||
// 180:
|
||||
// ffmpeg -noautorotate -i exif-orientation-originals\exif-orientation-test.psd -vf scale=128x96,transpose=2,transpose=2 -pix_fmt yuv420p -y temp.mp4
|
||||
// ffmpeg -i temp.mp4 -c copy -metadata:s:v:0 rotate=180 video-rotation-180.mp4
|
||||
// ffmpeg -noautorotate -i exif-orientation-originals\exif-orientation-test.psd -vf scale=128x96,transpose=2,transpose=2 -pix_fmt yuv420p -crf 0 -vcodec libvpx-vp9 -y temp.mp4
|
||||
// ffmpeg -i temp.mp4 -c copy -metadata:s:v:0 rotate=180 video-rotation-180.vp9.mp4
|
||||
//
|
||||
// 270:
|
||||
// ffmpeg -noautorotate -i exif-orientation-originals\exif-orientation-test.psd -vf scale=128x96,transpose=1 -pix_fmt yuv420p -y temp.mp4
|
||||
// ffmpeg -i temp.mp4 -c copy -metadata:s:v:0 rotate=90 video-rotation-270.mp4
|
||||
// ffmpeg -noautorotate -i exif-orientation-originals\exif-orientation-test.psd -vf scale=128x96,transpose=1 -pix_fmt yuv420p -crf 0 -vcodec libvpx-vp9 -y temp.mp4
|
||||
// ffmpeg -i temp.mp4 -c copy -metadata:s:v:0 rotate=90 video-rotation-270.vp9.mp4
|
||||
|
||||
const filenames = [
|
||||
"video-rotation-0",
|
||||
"video-rotation-90",
|
||||
"video-rotation-180",
|
||||
"video-rotation-270",
|
||||
];
|
||||
|
||||
if (supports_h264) {
|
||||
for (let fn of filenames)
|
||||
await testVideoElement(fn + ".mp4", false);
|
||||
}
|
||||
|
||||
if (supports_vp9) {
|
||||
for (let fn of filenames)
|
||||
await testVideoElement(fn + ".vp9.mp4", true);
|
||||
}
|
||||
})();
|
||||
|
||||
finishTest();
|
||||
}
|
||||
|
||||
var successfullyParsed = true;
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -164,9 +164,9 @@ function testInheritanceHierarchy() {
|
||||
|
||||
try {
|
||||
var foo = ArrayBufferView;
|
||||
testFailed('ArrayBufferView has [NoInterfaceObject] extended attribute and should not be defined');
|
||||
testFailed('ArrayBufferView is a typedef and should not be defined');
|
||||
} catch (e) {
|
||||
testPassed('ArrayBufferView has [NoInterfaceObject] extended attribute and was (correctly) not defined');
|
||||
testPassed('ArrayBufferView is a typedef and was (correctly) not defined');
|
||||
}
|
||||
|
||||
// Uint8ClampedArray inherited from Uint8Array in earlier versions
|
||||
|
@ -33,6 +33,25 @@ found in the LICENSE.txt file.
|
||||
gl_FragColor = vec4(color[0]$(elem), color[1]$(elem), color[2]$(elem), 1);
|
||||
}
|
||||
</script>
|
||||
<script id="vshader300" type="x-shader/x-vertex">
|
||||
#version 300 es
|
||||
in vec4 a_position;
|
||||
void main()
|
||||
{
|
||||
gl_Position = a_position;
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="fshader300" type="x-shader/x-fragment">
|
||||
#version 300 es
|
||||
precision mediump float;
|
||||
uniform $(type) color[3];
|
||||
out vec4 o_FragColor;
|
||||
void main()
|
||||
{
|
||||
o_FragColor = vec4(color[0]$(elem), color[1]$(elem), color[2]$(elem), 1);
|
||||
}
|
||||
</script>
|
||||
<script>
|
||||
"use strict";
|
||||
description();
|
||||
@ -42,10 +61,17 @@ var MaxInt32PlusOne = 4294967296;
|
||||
var wtu = WebGLTestUtils;
|
||||
var gl = wtu.create3DContext("example");
|
||||
|
||||
var vSrc = wtu.getScript("vshader");
|
||||
var fTemplate = wtu.getScript("fshader");
|
||||
const contextVersion = wtu.getDefault3DContextVersion();
|
||||
|
||||
var typeInfos = [
|
||||
let [vElemId, fElemId] = ["vshader", "fshader"];
|
||||
if (contextVersion >= 2) {
|
||||
[vElemId, fElemId] = ["vshader300", "fshader300"];
|
||||
}
|
||||
|
||||
var vSrc = wtu.getScript(vElemId).trim();
|
||||
var fTemplate = wtu.getScript(fElemId).trim();
|
||||
|
||||
const typeInfos = [
|
||||
{ type: 'float',
|
||||
jsTypeOf: 'number',
|
||||
setter: 'uniform1fv',
|
||||
@ -185,6 +211,428 @@ var typeInfos = [
|
||||
}
|
||||
];
|
||||
|
||||
if (contextVersion >= 2) {
|
||||
const more = [
|
||||
{ type: 'int',
|
||||
jsTypeOf: 'number',
|
||||
setter: 'uniform1iv',
|
||||
elem: '',
|
||||
numSrcValues: 3,
|
||||
invalidSet: function(loc) {
|
||||
gl.uniform2iv(loc, [1, 2]);
|
||||
},
|
||||
srcValueAsString: function(index, srcValues) {
|
||||
return srcValues[index].toString();
|
||||
},
|
||||
returnValueAsString: function(value) {
|
||||
return value === null ? 'null' : value.toString();
|
||||
},
|
||||
checkType: function(value) {
|
||||
return typeof value === 'number';
|
||||
},
|
||||
checkValue: function(typeInfo, index, value) {
|
||||
return typeInfo.srcValues[index] == value;
|
||||
},
|
||||
srcValues: [16, 15, 14],
|
||||
srcValuesLess: [],
|
||||
srcValuesLessMultiple: [16],
|
||||
srcValuesMoreMultiple: [16, 15, 14, 13],
|
||||
srcValuesNonMultiple: null,
|
||||
},
|
||||
{ type: 'ivec2',
|
||||
jsTypeOf: 'Int32Array',
|
||||
setter: 'uniform2iv',
|
||||
elem: '[1]',
|
||||
numSrcValues: 3,
|
||||
invalidSet: function(loc) {
|
||||
gl.uniform1iv(loc, [2]);
|
||||
},
|
||||
illegalSet: function(loc) {
|
||||
gl.uniform1iv(loc, 2);
|
||||
},
|
||||
srcValueAsString: function(index, srcValues) {
|
||||
return "[" + srcValues[index * 2 + 0].toString() + ", " +
|
||||
srcValues[index * 2 + 1].toString() + "]";
|
||||
},
|
||||
returnValueAsString: function(value) {
|
||||
return value === null ? 'null' : ("[" + value[0] + ", " + value[1] + "]");
|
||||
},
|
||||
checkType: function(value) {
|
||||
return value &&
|
||||
typeof value.length === 'number' &&
|
||||
value.length == 2;
|
||||
},
|
||||
checkValue: function(typeInfo, index, value) {
|
||||
return value !== null &&
|
||||
typeInfo.srcValues[index * 2 + 0] == value[0] &&
|
||||
typeInfo.srcValues[index * 2 + 1] == value[1];
|
||||
},
|
||||
srcValues: [16, 15, 14, 13, 12, 11],
|
||||
srcValuesLess: [16],
|
||||
srcValuesLessMultiple: [16, 15, 14, 13],
|
||||
srcValuesMoreMultiple: [16, 15, 14, 13, 12, 11, 10, 9],
|
||||
srcValuesNonMultiple: [16, 15, 14, 13, 12, 11, 10],
|
||||
},
|
||||
{ type: 'ivec3',
|
||||
jsTypeOf: 'Int32Array',
|
||||
setter: 'uniform3iv',
|
||||
elem: '[2]',
|
||||
numSrcValues: 3,
|
||||
invalidSet: function(loc) {
|
||||
gl.uniform1iv(loc, [2]);
|
||||
},
|
||||
illegalSet: function(loc) {
|
||||
gl.uniform1iv(loc, 2);
|
||||
},
|
||||
srcValueAsString: function(index, srcValues) {
|
||||
return "[" + srcValues[index * 3 + 0].toString() + ", " +
|
||||
srcValues[index * 3 + 1].toString() + ", " +
|
||||
srcValues[index * 3 + 2].toString() + "]";
|
||||
},
|
||||
returnValueAsString: function(value) {
|
||||
return value === null ? 'null' :
|
||||
("[" + value[0] + ", " + value[1] + ", " + value[2] + "]");
|
||||
},
|
||||
checkType: function(value) {
|
||||
return value &&
|
||||
typeof value.length === 'number' &&
|
||||
value.length == 3;
|
||||
},
|
||||
checkValue: function(typeInfo, index, value) {
|
||||
return value !== null &&
|
||||
typeInfo.srcValues[index * 3 + 0] == value[0] &&
|
||||
typeInfo.srcValues[index * 3 + 1] == value[1] &&
|
||||
typeInfo.srcValues[index * 3 + 2] == value[2];
|
||||
},
|
||||
srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8],
|
||||
srcValuesLess: [16, 15],
|
||||
srcValuesLessMultiple: [16, 15, 14, 13, 12, 11],
|
||||
srcValuesMoreMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2],
|
||||
srcValuesNonMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7],
|
||||
},
|
||||
{ type: 'ivec4',
|
||||
jsTypeOf: 'Int32Array',
|
||||
setter: 'uniform4iv',
|
||||
elem: '[3]',
|
||||
numSrcValues: 3,
|
||||
invalidSet: function(loc) {
|
||||
gl.uniform1iv(loc, [2]);
|
||||
},
|
||||
illegalSet: function(loc) {
|
||||
gl.uniform1iv(loc, 2);
|
||||
},
|
||||
srcValueAsString: function(index, srcValues) {
|
||||
return "[" + srcValues[index * 4 + 0].toString() + ", " +
|
||||
srcValues[index * 4 + 1].toString() + ", " +
|
||||
srcValues[index * 4 + 2].toString() + ", " +
|
||||
srcValues[index * 4 + 3].toString() + "]";
|
||||
},
|
||||
returnValueAsString: function(value) {
|
||||
return value === null ? 'null' :
|
||||
("[" + value[0] + ", " + value[1] +
|
||||
", " + value[2] + ", " + value[3] + "]");
|
||||
},
|
||||
checkType: function(value) {
|
||||
return value &&
|
||||
typeof value.length === 'number' &&
|
||||
value.length == 4;
|
||||
},
|
||||
checkValue: function(typeInfo, index, value) {
|
||||
return value !== null &&
|
||||
typeInfo.srcValues[index * 4 + 0] == value[0] &&
|
||||
typeInfo.srcValues[index * 4 + 1] == value[1] &&
|
||||
typeInfo.srcValues[index * 4 + 2] == value[2] &&
|
||||
typeInfo.srcValues[index * 4 + 3] == value[3];
|
||||
},
|
||||
srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
|
||||
srcValuesLess: [16, 15, 14],
|
||||
srcValuesLessMultiple: [16, 15, 14, 13, 12, 11, 10, 9],
|
||||
srcValuesMoreMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
|
||||
srcValuesNonMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4],
|
||||
},
|
||||
|
||||
|
||||
{ type: 'uint',
|
||||
jsTypeOf: 'number',
|
||||
setter: 'uniform1uiv',
|
||||
elem: '',
|
||||
numSrcValues: 3,
|
||||
invalidSet: function(loc) {
|
||||
gl.uniform2uiv(loc, [1, 2]);
|
||||
},
|
||||
srcValueAsString: function(index, srcValues) {
|
||||
return srcValues[index].toString();
|
||||
},
|
||||
returnValueAsString: function(value) {
|
||||
return value === null ? 'null' : value.toString();
|
||||
},
|
||||
checkType: function(value) {
|
||||
return typeof value === 'number';
|
||||
},
|
||||
checkValue: function(typeInfo, index, value) {
|
||||
return typeInfo.srcValues[index] == value;
|
||||
},
|
||||
srcValues: [16, 15, 14],
|
||||
srcValuesLess: [],
|
||||
srcValuesLessMultiple: [16],
|
||||
srcValuesMoreMultiple: [16, 15, 14, 13],
|
||||
srcValuesNonMultiple: null,
|
||||
},
|
||||
{ type: 'uvec2',
|
||||
jsTypeOf: 'Uint32Array',
|
||||
setter: 'uniform2uiv',
|
||||
elem: '[1]',
|
||||
numSrcValues: 3,
|
||||
invalidSet: function(loc) {
|
||||
gl.uniform1uiv(loc, [2]);
|
||||
},
|
||||
illegalSet: function(loc) {
|
||||
gl.uniform1uiv(loc, 2);
|
||||
},
|
||||
srcValueAsString: function(index, srcValues) {
|
||||
return "[" + srcValues[index * 2 + 0].toString() + ", " +
|
||||
srcValues[index * 2 + 1].toString() + "]";
|
||||
},
|
||||
returnValueAsString: function(value) {
|
||||
return value === null ? 'null' : ("[" + value[0] + ", " + value[1] + "]");
|
||||
},
|
||||
checkType: function(value) {
|
||||
return value &&
|
||||
typeof value.length === 'number' &&
|
||||
value.length == 2;
|
||||
},
|
||||
checkValue: function(typeInfo, index, value) {
|
||||
return value !== null &&
|
||||
typeInfo.srcValues[index * 2 + 0] == value[0] &&
|
||||
typeInfo.srcValues[index * 2 + 1] == value[1];
|
||||
},
|
||||
srcValues: [16, 15, 14, 13, 12, 11],
|
||||
srcValuesLess: [16],
|
||||
srcValuesLessMultiple: [16, 15, 14, 13],
|
||||
srcValuesMoreMultiple: [16, 15, 14, 13, 12, 11, 10, 9],
|
||||
srcValuesNonMultiple: [16, 15, 14, 13, 12, 11, 10],
|
||||
},
|
||||
{ type: 'uvec3',
|
||||
jsTypeOf: 'Uint32Array',
|
||||
setter: 'uniform3uiv',
|
||||
elem: '[2]',
|
||||
numSrcValues: 3,
|
||||
invalidSet: function(loc) {
|
||||
gl.uniform1uiv(loc, [2]);
|
||||
},
|
||||
illegalSet: function(loc) {
|
||||
gl.uniform1uiv(loc, 2);
|
||||
},
|
||||
srcValueAsString: function(index, srcValues) {
|
||||
return "[" + srcValues[index * 3 + 0].toString() + ", " +
|
||||
srcValues[index * 3 + 1].toString() + ", " +
|
||||
srcValues[index * 3 + 2].toString() + "]";
|
||||
},
|
||||
returnValueAsString: function(value) {
|
||||
return value === null ? 'null' :
|
||||
("[" + value[0] + ", " + value[1] + ", " + value[2] + "]");
|
||||
},
|
||||
checkType: function(value) {
|
||||
return value &&
|
||||
typeof value.length === 'number' &&
|
||||
value.length == 3;
|
||||
},
|
||||
checkValue: function(typeInfo, index, value) {
|
||||
return value !== null &&
|
||||
typeInfo.srcValues[index * 3 + 0] == value[0] &&
|
||||
typeInfo.srcValues[index * 3 + 1] == value[1] &&
|
||||
typeInfo.srcValues[index * 3 + 2] == value[2];
|
||||
},
|
||||
srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8],
|
||||
srcValuesLess: [16, 15],
|
||||
srcValuesLessMultiple: [16, 15, 14, 13, 12, 11],
|
||||
srcValuesMoreMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2],
|
||||
srcValuesNonMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7],
|
||||
},
|
||||
{ type: 'uvec4',
|
||||
jsTypeOf: 'Uint32Array',
|
||||
setter: 'uniform4uiv',
|
||||
elem: '[3]',
|
||||
numSrcValues: 3,
|
||||
invalidSet: function(loc) {
|
||||
gl.uniform1uiv(loc, [2]);
|
||||
},
|
||||
illegalSet: function(loc) {
|
||||
gl.uniform1uiv(loc, 2);
|
||||
},
|
||||
srcValueAsString: function(index, srcValues) {
|
||||
return "[" + srcValues[index * 4 + 0].toString() + ", " +
|
||||
srcValues[index * 4 + 1].toString() + ", " +
|
||||
srcValues[index * 4 + 2].toString() + ", " +
|
||||
srcValues[index * 4 + 3].toString() + "]";
|
||||
},
|
||||
returnValueAsString: function(value) {
|
||||
return value === null ? 'null' :
|
||||
("[" + value[0] + ", " + value[1] +
|
||||
", " + value[2] + ", " + value[3] + "]");
|
||||
},
|
||||
checkType: function(value) {
|
||||
return value &&
|
||||
typeof value.length === 'number' &&
|
||||
value.length == 4;
|
||||
},
|
||||
checkValue: function(typeInfo, index, value) {
|
||||
return value !== null &&
|
||||
typeInfo.srcValues[index * 4 + 0] == value[0] &&
|
||||
typeInfo.srcValues[index * 4 + 1] == value[1] &&
|
||||
typeInfo.srcValues[index * 4 + 2] == value[2] &&
|
||||
typeInfo.srcValues[index * 4 + 3] == value[3];
|
||||
},
|
||||
srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
|
||||
srcValuesLess: [16, 15, 14],
|
||||
srcValuesLessMultiple: [16, 15, 14, 13, 12, 11, 10, 9],
|
||||
srcValuesMoreMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
|
||||
srcValuesNonMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4],
|
||||
},
|
||||
|
||||
|
||||
{ type: 'bool',
|
||||
jsTypeOf: 'boolean',
|
||||
setter: 'uniform1iv',
|
||||
elem: '',
|
||||
numSrcValues: 3,
|
||||
invalidSet: function(loc) {
|
||||
gl.uniform2iv(loc, [1, 2]);
|
||||
},
|
||||
srcValueAsString: function(index, srcValues) {
|
||||
return srcValues[index].toString();
|
||||
},
|
||||
returnValueAsString: function(value) {
|
||||
return value === null ? 'null' : value.toString();
|
||||
},
|
||||
checkType: function(value) {
|
||||
return typeof value === 'boolean';
|
||||
},
|
||||
checkValue: function(typeInfo, index, value) {
|
||||
return typeInfo.srcValues[index] == value;
|
||||
},
|
||||
srcValues: [true, true, true],
|
||||
srcValuesLess: [],
|
||||
srcValuesLessMultiple: [16],
|
||||
srcValuesMoreMultiple: [16, 15, 14, 13],
|
||||
srcValuesNonMultiple: null,
|
||||
},
|
||||
{ type: 'bvec2',
|
||||
jsTypeOf: 'Float32Array',
|
||||
setter: 'uniform2fv',
|
||||
elem: '[1]',
|
||||
numSrcValues: 3,
|
||||
invalidSet: function(loc) {
|
||||
gl.uniform1iv(loc, [2]);
|
||||
},
|
||||
illegalSet: function(loc) {
|
||||
gl.uniform1iv(loc, 2);
|
||||
},
|
||||
srcValueAsString: function(index, srcValues) {
|
||||
return "[" + srcValues[index * 2 + 0].toString() + ", " +
|
||||
srcValues[index * 2 + 1].toString() + "]";
|
||||
},
|
||||
returnValueAsString: function(value) {
|
||||
return value === null ? 'null' : ("[" + value[0] + ", " + value[1] + "]");
|
||||
},
|
||||
checkType: function(value) {
|
||||
return value &&
|
||||
typeof value.length === 'number' &&
|
||||
value.length == 2;
|
||||
},
|
||||
checkValue: function(typeInfo, index, value) {
|
||||
return value !== null &&
|
||||
typeInfo.srcValues[index * 2 + 0] == value[0] &&
|
||||
typeInfo.srcValues[index * 2 + 1] == value[1];
|
||||
},
|
||||
srcValues: [true, true, true, true, true, true],
|
||||
srcValuesLess: [16],
|
||||
srcValuesLessMultiple: [16, 15, 14, 13],
|
||||
srcValuesMoreMultiple: [16, 15, 14, 13, 12, 11, 10, 9],
|
||||
srcValuesNonMultiple: [16, 15, 14, 13, 12, 11, 10],
|
||||
},
|
||||
{ type: 'bvec3',
|
||||
jsTypeOf: 'Int32Array',
|
||||
setter: 'uniform3iv',
|
||||
elem: '[2]',
|
||||
numSrcValues: 3,
|
||||
invalidSet: function(loc) {
|
||||
gl.uniform1iv(loc, [2]);
|
||||
},
|
||||
illegalSet: function(loc) {
|
||||
gl.uniform1iv(loc, 2);
|
||||
},
|
||||
srcValueAsString: function(index, srcValues) {
|
||||
return "[" + srcValues[index * 3 + 0].toString() + ", " +
|
||||
srcValues[index * 3 + 1].toString() + ", " +
|
||||
srcValues[index * 3 + 2].toString() + "]";
|
||||
},
|
||||
returnValueAsString: function(value) {
|
||||
return value === null ? 'null' :
|
||||
("[" + value[0] + ", " + value[1] + ", " + value[2] + "]");
|
||||
},
|
||||
checkType: function(value) {
|
||||
return value &&
|
||||
typeof value.length === 'number' &&
|
||||
value.length == 3;
|
||||
},
|
||||
checkValue: function(typeInfo, index, value) {
|
||||
return value !== null &&
|
||||
typeInfo.srcValues[index * 3 + 0] == value[0] &&
|
||||
typeInfo.srcValues[index * 3 + 1] == value[1] &&
|
||||
typeInfo.srcValues[index * 3 + 2] == value[2];
|
||||
},
|
||||
srcValues: [true, true, true, true, true, true, true, true, true],
|
||||
srcValuesLess: [16, 15],
|
||||
srcValuesLessMultiple: [16, 15, 14, 13, 12, 11],
|
||||
srcValuesMoreMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2],
|
||||
srcValuesNonMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7],
|
||||
},
|
||||
{ type: 'bvec4',
|
||||
jsTypeOf: 'Uint32Array',
|
||||
setter: 'uniform4uiv',
|
||||
elem: '[3]',
|
||||
numSrcValues: 3,
|
||||
invalidSet: function(loc) {
|
||||
gl.uniform1iv(loc, [2]);
|
||||
},
|
||||
illegalSet: function(loc) {
|
||||
gl.uniform1iv(loc, 2);
|
||||
},
|
||||
srcValueAsString: function(index, srcValues) {
|
||||
return "[" + srcValues[index * 4 + 0].toString() + ", " +
|
||||
srcValues[index * 4 + 1].toString() + ", " +
|
||||
srcValues[index * 4 + 2].toString() + ", " +
|
||||
srcValues[index * 4 + 3].toString() + "]";
|
||||
},
|
||||
returnValueAsString: function(value) {
|
||||
return value === null ? 'null' :
|
||||
("[" + value[0] + ", " + value[1] +
|
||||
", " + value[2] + ", " + value[3] + "]");
|
||||
},
|
||||
checkType: function(value) {
|
||||
return value &&
|
||||
typeof value.length === 'number' &&
|
||||
value.length == 4;
|
||||
},
|
||||
checkValue: function(typeInfo, index, value) {
|
||||
return value !== null &&
|
||||
typeInfo.srcValues[index * 4 + 0] == value[0] &&
|
||||
typeInfo.srcValues[index * 4 + 1] == value[1] &&
|
||||
typeInfo.srcValues[index * 4 + 2] == value[2] &&
|
||||
typeInfo.srcValues[index * 4 + 3] == value[3];
|
||||
},
|
||||
srcValues: [true, true, true, true, true, true, true, true, true, true, true, true],
|
||||
srcValuesLess: [16, 15, 14],
|
||||
srcValuesLessMultiple: [16, 15, 14, 13, 12, 11, 10, 9],
|
||||
srcValuesMoreMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
|
||||
srcValuesNonMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4],
|
||||
}
|
||||
];
|
||||
typeInfos.push(...more);
|
||||
}
|
||||
|
||||
let loc;
|
||||
for (var tt = 0; tt < typeInfos.length; ++tt) {
|
||||
var typeInfo = typeInfos[tt];
|
||||
debug("");
|
||||
@ -199,7 +647,8 @@ for (var tt = 0; tt < typeInfos.length; ++tt) {
|
||||
assertMsg(info.name == "color[0]",
|
||||
"uniform name is 'color[0]' not 'color' as per OpenGL ES 2.0.24 section 2.10");
|
||||
shouldBeNull("gl.getUniformLocation(program, 'color[" + MaxInt32PlusOne + "]');");
|
||||
var loc = gl.getUniformLocation(program, "color[0]");
|
||||
loc = gl.getUniformLocation(program, "color[0]");
|
||||
if (!loc) throw 'Missing loc';
|
||||
var srcValues = typeInfo.srcValues;
|
||||
var srcValuesLess = typeInfo.srcValuesLess;
|
||||
var srcValuesLessMultiple = typeInfo.srcValuesLessMultiple;
|
||||
@ -220,6 +669,20 @@ for (var tt = 0; tt < typeInfos.length; ++tt) {
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
|
||||
"should fail with non-multiple array size with gl." + typeInfo.setter);
|
||||
}
|
||||
|
||||
const validDatas = [
|
||||
`new Float32Array(${srcValues.length})`,
|
||||
`new Float32Array(new ArrayBuffer(4*${srcValues.length}))`,
|
||||
];
|
||||
if (window.SharedArrayBuffer) {
|
||||
validDatas.push(
|
||||
`new Float32Array(new SharedArrayBuffer(4*${srcValues.length}))`
|
||||
);
|
||||
}
|
||||
for (const x of validDatas) {
|
||||
shouldNotThrow(`gl.${typeInfo.setter}(loc, ${x});`);
|
||||
}
|
||||
|
||||
gl[typeInfo.setter](loc, srcValues);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR,
|
||||
"can set an array of uniforms with gl." + typeInfo.setter);
|
||||
@ -234,7 +697,7 @@ for (var tt = 0; tt < typeInfos.length; ++tt) {
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR,
|
||||
"can call gl.getUniform");
|
||||
assertMsg(typeInfo.checkType(values),
|
||||
"gl.getUniform returns the correct type.");
|
||||
"gl.getUniform returns the correct type. " + `(was ${values.constructor.name})`);
|
||||
for (var ii = 0; ii < typeInfo.numSrcValues; ++ii) {
|
||||
shouldBeNull("gl.getUniformLocation(program, 'color[" + (MaxInt32PlusOne + ii) + "]')");
|
||||
var elemLoc = gl.getUniformLocation(program, "color[" + ii + "]");
|
||||
|
@ -19,23 +19,49 @@ found in the LICENSE.txt file.
|
||||
<canvas id="example" width="2" height="2"> </canvas>
|
||||
|
||||
<script id="vshader" type="x-shader/x-vertex">
|
||||
attribute vec4 vPosition;
|
||||
uniform mat4 world4;
|
||||
uniform mat3 world3;
|
||||
uniform mat2 world2;
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(vPosition.xyz, world3[0].x + world2[0].x) * world4;
|
||||
uniform mat2 world2x2;
|
||||
uniform mat3 world3x3;
|
||||
uniform mat4 world4x4;
|
||||
void main() {
|
||||
gl_Position.x += world2x2[0][0];
|
||||
gl_Position.x += world3x3[0][0];
|
||||
gl_Position.x += world4x4[0][0];
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="fshader" type="x-shader/x-fragment">
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
|
||||
void main() {}
|
||||
</script>
|
||||
|
||||
<script id="vshader300" type="x-shader/x-vertex">
|
||||
#version 300 es
|
||||
uniform mat2 world2x2;
|
||||
uniform mat2x3 world2x3;
|
||||
uniform mat2x4 world2x4;
|
||||
uniform mat3x2 world3x2;
|
||||
uniform mat3 world3x3;
|
||||
uniform mat3x4 world3x4;
|
||||
uniform mat4x2 world4x2;
|
||||
uniform mat4x3 world4x3;
|
||||
uniform mat4 world4x4;
|
||||
void main() {
|
||||
gl_Position.x += world2x2[0][0];
|
||||
gl_Position.x += world2x3[0][0];
|
||||
gl_Position.x += world2x4[0][0];
|
||||
gl_Position.x += world3x2[0][0];
|
||||
gl_Position.x += world3x3[0][0];
|
||||
gl_Position.x += world3x4[0][0];
|
||||
gl_Position.x += world4x2[0][0];
|
||||
gl_Position.x += world4x3[0][0];
|
||||
gl_Position.x += world4x4[0][0];
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="fshader300" type="x-shader/x-fragment">
|
||||
#version 300 es
|
||||
void main() {}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
description("This test ensures WebGL implementations handle uniformMatrix in a OpenGL ES 2.0 spec compliant way");
|
||||
@ -46,20 +72,42 @@ debug("Checking gl.uniformMatrix.");
|
||||
var wtu = WebGLTestUtils;
|
||||
var gl = wtu.create3DContext("example");
|
||||
var contextVersion = wtu.getDefault3DContextVersion();
|
||||
var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["vPosition"]);
|
||||
for (var ii = 2; ii <= 4; ++ii) {
|
||||
var loc = gl.getUniformLocation(program, "world" + ii);
|
||||
var matLess = [];
|
||||
for (var jj = 0; jj < ii; ++jj) {
|
||||
for (var ll = 0; ll < ii; ++ll) {
|
||||
if (jj == ii - 1 && ll == ii - 1)
|
||||
continue;
|
||||
matLess[jj * ii + ll] = (jj == ll) ? 1 : 0;
|
||||
|
||||
let shaders = ["vshader", "fshader"];
|
||||
const dims = [
|
||||
[2, 2, 'uniformMatrix2fv'],
|
||||
[3, 3, 'uniformMatrix3fv'],
|
||||
[4, 4, 'uniformMatrix4fv'],
|
||||
];
|
||||
|
||||
if (contextVersion >= 2) {
|
||||
shaders = ["vshader300", "fshader300"];
|
||||
dims.push(
|
||||
[2, 3, 'uniformMatrix2x3fv'],
|
||||
[2, 4, 'uniformMatrix2x4fv'],
|
||||
[3, 2, 'uniformMatrix3x2fv'],
|
||||
[3, 4, 'uniformMatrix3x4fv'],
|
||||
[4, 2, 'uniformMatrix4x2fv'],
|
||||
[4, 3, 'uniformMatrix4x3fv']
|
||||
);
|
||||
}
|
||||
|
||||
const program = wtu.setupProgram(gl, shaders);
|
||||
let loc;
|
||||
|
||||
for (const [A, B, name] of dims) {
|
||||
loc = gl.getUniformLocation(program, `world${A}x${B}`);
|
||||
if (!loc) throw 'missing loc';
|
||||
|
||||
const mat = [];
|
||||
for (let a = 0; a < A; ++a) {
|
||||
for (let b = 0; b < B; ++b) {
|
||||
mat.push((a == b) ? 1 : 0);
|
||||
}
|
||||
}
|
||||
var mat = matLess.concat([1]);
|
||||
var matMore = mat.concat([1]);
|
||||
name = "uniformMatrix" + ii + "fv";
|
||||
const matLess = mat.slice(0, mat.length-2);
|
||||
const matMore = mat.concat([1]);
|
||||
|
||||
gl[name](loc, false, matLess);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "should fail with insufficient array size for " + name);
|
||||
gl[name](loc, false, mat);
|
||||
@ -67,7 +115,19 @@ for (var ii = 2; ii <= 4; ++ii) {
|
||||
gl[name](loc, false, matMore);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "should fail with more than 1 array size for " + name);
|
||||
|
||||
mat[ii * ii - 1] = 1;
|
||||
const validDatas = [
|
||||
`new Float32Array(${mat.length})`,
|
||||
`new Float32Array(new ArrayBuffer(4*${mat.length}))`,
|
||||
];
|
||||
if (window.SharedArrayBuffer) {
|
||||
validDatas.push(
|
||||
`new Float32Array(new SharedArrayBuffer(4*${mat.length}))`
|
||||
);
|
||||
}
|
||||
for (const x of validDatas) {
|
||||
shouldNotThrow(`gl.${name}(loc, false, ${x});`);
|
||||
}
|
||||
|
||||
gl[name](loc, false, mat);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "can call " + name + "with transpose = false");
|
||||
if (contextVersion <= 1) {
|
||||
|
@ -16,8 +16,8 @@ found in the LICENSE.txt file.
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
|
||||
<canvas id="canvas2d" width="40" height="40"> </canvas>
|
||||
<canvas id="canvas1" style="width: 50px; height: 50px;"> </canvas>
|
||||
<canvas id="canvas2" style="width: 50px; height: 50px;"> </canvas>
|
||||
<script>
|
||||
"use strict";
|
||||
description("This test ensures WebGL2 implementations interact correctly with the canvas tag.");
|
||||
@ -25,24 +25,53 @@ description("This test ensures WebGL2 implementations interact correctly with th
|
||||
debug("");
|
||||
debug("Canvas.getContext");
|
||||
|
||||
assertMsg(window.WebGLRenderingContext,
|
||||
"WebGL2RenderingContext should be a member of window");
|
||||
assertMsg('WebGL2RenderingContext' in window,
|
||||
"WebGL2RenderingContext should be 'in' window");
|
||||
function runTest() {
|
||||
assertMsg(window.WebGL2RenderingContext,
|
||||
"WebGL2RenderingContext should be a member of window");
|
||||
assertMsg('WebGL2RenderingContext' in window,
|
||||
"WebGL2RenderingContext should be 'in' window");
|
||||
|
||||
var wtu = WebGLTestUtils;
|
||||
var canvas = document.getElementById("canvas");
|
||||
var gl = wtu.create3DContext(canvas, null, 2);
|
||||
if (!gl) {
|
||||
testFailed("context does not exist");
|
||||
} else {
|
||||
testPassed("context exists");
|
||||
const wtu = WebGLTestUtils;
|
||||
let canvas2 = document.getElementById("canvas2");
|
||||
let gl2 = wtu.create3DContext(canvas2, null, 2);
|
||||
if (!gl2) {
|
||||
testFailed("Could not fetch WebGL 2.0 context");
|
||||
return;
|
||||
}
|
||||
testPassed("Fetched WebGL2 context successfully");
|
||||
|
||||
debug("Checking context type");
|
||||
assertMsg(gl instanceof WebGL2RenderingContext,
|
||||
debug("Checking WebGL2 context type");
|
||||
assertMsg(gl2 instanceof WebGL2RenderingContext,
|
||||
"context type should be WebGL2RenderingContext");
|
||||
|
||||
// WebGL1 contexts do not respond to the WebGL2 context type, and vice versa.
|
||||
let canvas1 = document.getElementById("canvas1");
|
||||
let gl1 = wtu.create3DContext(canvas1, null, 1);
|
||||
if (!gl1) {
|
||||
testFailed("Could not fetch WebGL 1.0 context");
|
||||
return;
|
||||
}
|
||||
|
||||
debug("Checking WebGL1 context type");
|
||||
assertMsg(gl1 instanceof WebGLRenderingContext,
|
||||
"context type should be WebGLRenderingContext");
|
||||
|
||||
let msg1 = "A canvas which has created a WebGL 1.0 context should not return it for a 'webgl2' context request";
|
||||
if (canvas1.getContext("webgl2"))
|
||||
testFailed(msg1);
|
||||
else
|
||||
testPassed(msg1);
|
||||
|
||||
let msg2 = "A canvas which has created a WebGL 2.0 context should not return it for a 'webgl' context request";
|
||||
if (canvas2.getContext("webgl"))
|
||||
testFailed(msg2);
|
||||
else
|
||||
testPassed(msg2);
|
||||
}
|
||||
|
||||
runTest();
|
||||
debug("");
|
||||
|
||||
var successfullyParsed = true;
|
||||
</script>
|
||||
<script src="../../js/js-test-post.js"></script>
|
||||
|
@ -11,6 +11,7 @@ found in the LICENSE.txt file.
|
||||
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
|
||||
<script src="../../js/js-test-pre.js"></script>
|
||||
<script src="../../js/webgl-test-utils.js"></script>
|
||||
<script src="../../js/tests/context-methods.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
@ -20,7 +21,7 @@ found in the LICENSE.txt file.
|
||||
"use strict";
|
||||
description("This test ensures that the WebGL context has all the methods in the specification.");
|
||||
|
||||
var methods = [
|
||||
const methods = [
|
||||
"getContextAttributes",
|
||||
"activeTexture",
|
||||
"attachShader",
|
||||
@ -249,55 +250,14 @@ var methods = [
|
||||
"bindVertexArray",
|
||||
];
|
||||
|
||||
// Properties to be ignored because they were added in versions of the
|
||||
// spec that are backward-compatible with this version
|
||||
var ignoredMethods = [
|
||||
// There is no official spec for the commit API yet, the proposal link is:
|
||||
// https://wiki.whatwg.org/wiki/OffscreenCanvas
|
||||
"commit"
|
||||
];
|
||||
|
||||
function assertFunction(v, f) {
|
||||
try {
|
||||
if (typeof v[f] != "function") {
|
||||
testFailed("Property either does not exist or is not a function: " + f);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} catch(e) {
|
||||
testFailed("Trying to access the property '" + f + "' threw an error: "+e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
debug("");
|
||||
debug("Canvas.getContext");
|
||||
|
||||
var wtu = WebGLTestUtils;
|
||||
var canvas = document.getElementById("canvas");
|
||||
var gl = wtu.create3DContext(canvas, null, 2);
|
||||
var passed = true;
|
||||
for (var i=0; i<methods.length; i++) {
|
||||
var r = assertFunction(gl, methods[i]);
|
||||
passed = passed && r;
|
||||
}
|
||||
if (passed) {
|
||||
testPassed("All WebGL methods found.");
|
||||
}
|
||||
var extended = false;
|
||||
for (var i in gl) {
|
||||
if (typeof gl[i] == "function" && methods.indexOf(i) == -1 && ignoredMethods.indexOf(i) == -1) {
|
||||
if (!extended) {
|
||||
extended = true;
|
||||
testFailed("Also found the following extra methods:");
|
||||
}
|
||||
testFailed(i);
|
||||
}
|
||||
}
|
||||
const wtu = WebGLTestUtils;
|
||||
const canvas = document.getElementById("canvas");
|
||||
const gl = wtu.create3DContext(canvas, null, 2);
|
||||
|
||||
if (!extended) {
|
||||
testPassed("No extra methods found on WebGL context.");
|
||||
}
|
||||
testContextMethods(gl, methods);
|
||||
|
||||
debug("");
|
||||
var successfullyParsed = true;
|
||||
|
@ -1,9 +1,11 @@
|
||||
ext-color-buffer-float.html
|
||||
--min-version 2.0.1 ext-color-buffer-half-float.html
|
||||
ext-disjoint-timer-query-webgl2.html
|
||||
--min-version 2.0.1 ext-texture-filter-anisotropic.html
|
||||
--min-version 2.0.1 ext-texture-norm16.html
|
||||
promoted-extensions.html
|
||||
promoted-extensions-in-shaders.html
|
||||
--min-version 2.0.1 oes-draw-buffers-indexed.html
|
||||
--min-version 2.0.1 ovr_multiview2.html
|
||||
--min-version 2.0.1 ovr_multiview2_depth.html
|
||||
--min-version 2.0.1 ovr_multiview2_draw_buffers.html
|
||||
|
@ -284,7 +284,7 @@ function runInternalFormatQueryTest()
|
||||
debug("testing the internal format query");
|
||||
|
||||
var maxSamples = gl.getParameter(gl.MAX_SAMPLES);
|
||||
var formats = new Array(gl.RGBA16F, gl.R32F, gl.RG32F, gl.RGBA32F, gl.R16F, gl.RG16F, gl.R11F_G11F_B10F);
|
||||
const formats = [gl.RGBA16F, gl.R32F, gl.RG32F, gl.RGBA32F, gl.R16F, gl.RG16F, gl.R11F_G11F_B10F];
|
||||
var firstMultiOnlyFormat = 4;
|
||||
for (var fmt = 0; fmt < formats.length; ++fmt) {
|
||||
var samples = gl.getInternalformatParameter(gl.RENDERBUFFER, formats[fmt], gl.SAMPLES);
|
||||
|
@ -0,0 +1,27 @@
|
||||
<!--
|
||||
Copyright (c) 2020 The Khronos Group Inc.
|
||||
Use of this source code is governed by an MIT-style license that can be
|
||||
found in the LICENSE.txt file.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>WebGL 2 EXT_color_buffer_half_float Conformance Tests</title>
|
||||
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
|
||||
<script src="../../js/js-test-pre.js"></script>
|
||||
<script src="../../js/webgl-test-utils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
|
||||
<div id="console"></div>
|
||||
<script>
|
||||
var version = 2;
|
||||
</script>
|
||||
<script src="../../js/tests/ext-color-buffer-half-float.js"></script>
|
||||
<script src="../../js/js-test-post.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -23,7 +23,7 @@ description("This test verifies the functionality of the EXT_texture_norm16 exte
|
||||
debug("");
|
||||
|
||||
var wtu = WebGLTestUtils;
|
||||
var gl = wtu.create3DContext();
|
||||
var gl = wtu.create3DContext(null, null, 2);
|
||||
var ext;
|
||||
|
||||
var formats = null;
|
||||
@ -138,6 +138,38 @@ function testNorm16Render(interalFormat, format, type, tolerance) {
|
||||
gl.bindTexture(gl.TEXTURE_2D, null);
|
||||
}
|
||||
|
||||
function testSnorm16Unrenderable(internalFormat, format, type) {
|
||||
gl.bindTexture(gl.TEXTURE_2D, textures[1]);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, 1, 1, 0, format, type, null);
|
||||
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texture definition succeeded");
|
||||
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, fbos[0]);
|
||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, textures[1], 0);
|
||||
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "fbo binding succeeded");
|
||||
|
||||
wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER, [ gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT, gl.FRAMEBUFFER_UNSUPPORTED ],
|
||||
"framebuffer should not be complete with SNORM16 texture attached");
|
||||
}
|
||||
|
||||
function runInternalFormatQueryTest()
|
||||
{
|
||||
debug("");
|
||||
debug("testing the internal format query");
|
||||
|
||||
var maxSamples = gl.getParameter(gl.MAX_SAMPLES);
|
||||
const formats = [ext.R16_EXT, ext.RG16_EXT, ext.RGBA16_EXT];
|
||||
for (const format of formats) {
|
||||
var samples = gl.getInternalformatParameter(gl.RENDERBUFFER, format, gl.SAMPLES);
|
||||
if (samples == null || samples.length == 0 || samples[0] < maxSamples) {
|
||||
testFailed("the maximum value in SAMPLES should be at least " + maxSamples);
|
||||
return;
|
||||
}
|
||||
}
|
||||
testPassed("Internal format query succeeded");
|
||||
}
|
||||
|
||||
function runTestExtension() {
|
||||
textures = [gl.createTexture(), gl.createTexture()];
|
||||
fbos = [gl.createFramebuffer(), gl.createFramebuffer()];
|
||||
@ -174,6 +206,11 @@ function runTestExtension() {
|
||||
testNorm16Render(ext.R16_EXT, gl.RED, gl.UNSIGNED_SHORT, 0);
|
||||
testNorm16Render(ext.RG16_EXT, gl.RG, gl.UNSIGNED_SHORT, 0);
|
||||
testNorm16Render(ext.RGBA16_EXT, gl.RGBA, gl.UNSIGNED_SHORT, 0);
|
||||
|
||||
testSnorm16Unrenderable(ext.R16_SNORM_EXT, gl.RED, gl.SHORT);
|
||||
testSnorm16Unrenderable(ext.RG16_SNORM_EXT, gl.RG, gl.SHORT);
|
||||
testSnorm16Unrenderable(ext.RGB16_SNORM_EXT, gl.RGB, gl.SHORT);
|
||||
testSnorm16Unrenderable(ext.RGBA16_SNORM_EXT, gl.RGBA, gl.SHORT);
|
||||
};
|
||||
|
||||
function runTest() {
|
||||
@ -187,6 +224,7 @@ function runTest() {
|
||||
wtu.runExtensionSupportedTest(gl, "EXT_texture_norm16", ext !== null);
|
||||
|
||||
if (ext !== null) {
|
||||
runInternalFormatQueryTest();
|
||||
runTestExtension();
|
||||
} else {
|
||||
testPassed("No EXT_texture_norm16 support -- this is legal");
|
||||
|
@ -0,0 +1,545 @@
|
||||
<!--
|
||||
Copyright (c) 2020 The Khronos Group Inc.
|
||||
Use of this source code is governed by an MIT-style license that can be
|
||||
found in the LICENSE.txt file.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>WebGL OES_draw_buffers_indexed Conformance Tests</title>
|
||||
<LINK rel="stylesheet" href="../../resources/js-test-style.css"/>
|
||||
<script src="../../js/js-test-pre.js"></script>
|
||||
<script src="../../js/webgl-test-utils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<script>
|
||||
"use strict";
|
||||
description("This test verifies the functionality of the OES_draw_buffers_indexed extension, if it is available.");
|
||||
|
||||
debug("");
|
||||
|
||||
var wtu = WebGLTestUtils;
|
||||
var canvas = document.getElementById("canvas");
|
||||
var gl = wtu.create3DContext(null, null, 2);
|
||||
var ext;
|
||||
|
||||
const vs = `#version 300 es
|
||||
layout(location=0) in vec4 vPosition;
|
||||
void main()
|
||||
{
|
||||
gl_Position = vPosition;
|
||||
}
|
||||
`;
|
||||
|
||||
const fs = `#version 300 es
|
||||
precision lowp float;
|
||||
layout(location = 0) out vec4 o_color0;
|
||||
layout(location = 1) out vec4 o_color1;
|
||||
void main()
|
||||
{
|
||||
o_color0 = vec4(1, 0, 0, 0);
|
||||
o_color1 = vec4(1, 0, 0, 0);
|
||||
}
|
||||
`;
|
||||
|
||||
function setup() {
|
||||
const program = wtu.setupProgram(gl, [vs, fs]);
|
||||
gl.useProgram(program);
|
||||
wtu.setupUnitQuad(gl, 0);
|
||||
wtu.glErrorShouldBe(gl, 0, 'No errors from program');
|
||||
|
||||
const tex1 = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex1);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
||||
wtu.glErrorShouldBe(gl, 0, 'Create texture 1 successfully');
|
||||
|
||||
const tex2 = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex2);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
||||
wtu.glErrorShouldBe(gl, 0, 'Create texture 2 successfully');
|
||||
|
||||
const attachments = [gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1];
|
||||
|
||||
const fb = gl.createFramebuffer();
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
|
||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, attachments[0], gl.TEXTURE_2D, tex1, 0);
|
||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, attachments[1], gl.TEXTURE_2D, tex2, 0);
|
||||
shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
|
||||
|
||||
gl.drawBuffers(attachments);
|
||||
wtu.glErrorShouldBe(gl, 0, 'Set draw buffers without errors');
|
||||
}
|
||||
|
||||
function enableDisableTest() {
|
||||
debug("Testing enableiOES/disableiOES");
|
||||
|
||||
// Invalid input
|
||||
ext.enableiOES(gl.DEPTH_TEST, 0);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'target could only be gl.BLEND');
|
||||
|
||||
ext.disableiOES(gl.DEPTH_TEST, 0);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'target could only be gl.BLEND');
|
||||
|
||||
gl.disable(gl.BLEND);
|
||||
|
||||
// Valid input
|
||||
ext.enableiOES(gl.BLEND, 0);
|
||||
shouldBe('gl.isEnabled(gl.BLEND)', 'true');
|
||||
ext.disableiOES(gl.BLEND, 0);
|
||||
ext.enableiOES(gl.BLEND, 1);
|
||||
shouldBe('gl.isEnabled(gl.BLEND)', 'false');
|
||||
gl.enable(gl.BLEND);
|
||||
shouldBe('gl.isEnabled(gl.BLEND)', 'true');
|
||||
wtu.glErrorShouldBe(gl, 0, 'No errors from enable and disable draw buffers blend state');
|
||||
}
|
||||
|
||||
function constantAlphaBlendColorValidationTest() {
|
||||
debug("Testing CONSTANT_COLOR/ALPHA blend functions limit validation");
|
||||
function isConstantColorAndAlphaBlendFunctions(first, second)
|
||||
{
|
||||
return (first == gl.CONSTANT_COLOR || first == gl.ONE_MINUS_CONSTANT_COLOR) &&
|
||||
(second == gl.CONSTANT_ALPHA || second == gl.ONE_MINUS_CONSTANT_ALPHA);
|
||||
}
|
||||
|
||||
function checkBlendFunctions(src, dst)
|
||||
{
|
||||
if (isConstantColorAndAlphaBlendFunctions(src, dst) ||
|
||||
isConstantColorAndAlphaBlendFunctions(dst, src))
|
||||
{
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, 'invalid combinations');
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
wtu.glErrorShouldBe(gl, 0, 'No error');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const srcFunc = [
|
||||
gl.ZERO,
|
||||
gl.ONE,
|
||||
gl.SRC_COLOR,
|
||||
gl.ONE_MINUS_SRC_COLOR,
|
||||
gl.DST_COLOR,
|
||||
gl.ONE_MINUS_DST_COLOR,
|
||||
gl.SRC_ALPHA,
|
||||
gl.ONE_MINUS_SRC_ALPHA,
|
||||
gl.DST_ALPHA,
|
||||
gl.ONE_MINUS_DST_ALPHA,
|
||||
gl.CONSTANT_COLOR,
|
||||
gl.ONE_MINUS_CONSTANT_COLOR,
|
||||
gl.CONSTANT_ALPHA,
|
||||
gl.ONE_MINUS_CONSTANT_ALPHA,
|
||||
gl.SRC_ALPHA_SATURATE,
|
||||
];
|
||||
|
||||
const dstFunc = [
|
||||
gl.ZERO, gl.ONE,
|
||||
gl.SRC_COLOR, gl.ONE_MINUS_SRC_COLOR,
|
||||
gl.DST_COLOR, gl.ONE_MINUS_DST_COLOR,
|
||||
gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA,
|
||||
gl.DST_ALPHA, gl.ONE_MINUS_DST_ALPHA,
|
||||
gl.CONSTANT_COLOR, gl.ONE_MINUS_CONSTANT_COLOR,
|
||||
gl.CONSTANT_ALPHA, gl.ONE_MINUS_CONSTANT_ALPHA,
|
||||
];
|
||||
|
||||
let src, dst;
|
||||
|
||||
// CONSTANT_COLOR/ALPHA invalid combination check
|
||||
for (let i = 0, leni = srcFunc.length; i < leni; i++)
|
||||
{
|
||||
src = srcFunc[i];
|
||||
for (let j = 0, lenj = dstFunc.length; j < lenj; j++)
|
||||
{
|
||||
dst = dstFunc[j];
|
||||
ext.blendFunciOES(0, src, dst);
|
||||
checkBlendFunctions(src, dst);
|
||||
ext.blendFuncSeparateiOES(0, src, dst, gl.ONE, gl.ONE);
|
||||
checkBlendFunctions(src, dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function indexedBlendColorTest() {
|
||||
debug('');
|
||||
debug("Testing blendEquationiOES and blendFunciOES");
|
||||
wtu.glErrorShouldBe(gl, 0, 'top of indexedBlendColorTest');
|
||||
|
||||
gl.clearColor(0, 0, 1, 1);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
ext.blendEquationiOES(0, gl.FUNC_ADD);
|
||||
ext.blendFunciOES(0, gl.ONE, gl.ONE);
|
||||
ext.blendEquationiOES(1, gl.FUNC_ADD);
|
||||
ext.blendFunciOES(1, gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
||||
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
||||
wtu.glErrorShouldBe(gl, 0, 'Draw quad without errors');
|
||||
|
||||
gl.readBuffer(gl.COLOR_ATTACHMENT0);
|
||||
wtu.checkCanvasRect(gl, 0, 0, 1, 1, [255, 0, 255, 255]);
|
||||
|
||||
gl.readBuffer(gl.COLOR_ATTACHMENT1);
|
||||
wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 255, 255]);
|
||||
|
||||
debug("Testing blendEquationSeparateiOES and blendFuncSeparateiOES");
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
ext.blendEquationSeparateiOES(0, gl.FUNC_ADD, gl.FUNC_SUBTRACT);
|
||||
ext.blendFuncSeparateiOES(0, gl.ONE, gl.ONE, gl.ZERO, gl.ZERO);
|
||||
ext.blendEquationSeparateiOES(1, gl.FUNC_ADD, gl.FUNC_SUBTRACT);
|
||||
ext.blendFuncSeparateiOES(1, gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ZERO, gl.ZERO);
|
||||
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
||||
wtu.glErrorShouldBe(gl, 0, 'Draw quad without errors');
|
||||
|
||||
gl.readBuffer(gl.COLOR_ATTACHMENT0);
|
||||
wtu.checkCanvasRect(gl, 0, 0, 1, 1, [255, 0, 255, 0]);
|
||||
|
||||
gl.readBuffer(gl.COLOR_ATTACHMENT1);
|
||||
wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 255, 0]);
|
||||
|
||||
debug("Testing colorMaskiOES");
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
ext.colorMaskiOES(0, false, false, false, false);
|
||||
ext.colorMaskiOES(1, true, true, true, true);
|
||||
|
||||
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
||||
wtu.glErrorShouldBe(gl, 0, 'Draw quad without errors');
|
||||
|
||||
gl.readBuffer(gl.COLOR_ATTACHMENT0);
|
||||
wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 255, 255]);
|
||||
|
||||
gl.readBuffer(gl.COLOR_ATTACHMENT1);
|
||||
wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 255, 0]);
|
||||
|
||||
debug('');
|
||||
debug(`Testing that new tokens aren't on the extension.`);
|
||||
shouldBe('ext.BLEND_EQUATION_RGB', 'undefined');
|
||||
shouldBe('ext.BLEND_EQUATION_ALPHA', 'undefined');
|
||||
shouldBe('ext.BLEND_SRC_RGB', 'undefined');
|
||||
shouldBe('ext.BLEND_SRC_ALPHA', 'undefined');
|
||||
shouldBe('ext.BLEND_DST_RGB', 'undefined');
|
||||
shouldBe('ext.BLEND_DST_ALPHA', 'undefined');
|
||||
shouldBe('ext.COLOR_WRITEMASK', 'undefined');
|
||||
|
||||
debug("Testing new tokens for getIndexedParameterTest");
|
||||
shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_RGB, 0)', 'gl.FUNC_ADD');
|
||||
shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_ALPHA, 0)', 'gl.FUNC_SUBTRACT');
|
||||
shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_RGB, 0)', 'gl.ONE');
|
||||
shouldBe('gl.getIndexedParameter(gl.BLEND_DST_RGB, 0)', 'gl.ONE');
|
||||
shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_ALPHA, 0)', 'gl.ZERO');
|
||||
shouldBe('gl.getIndexedParameter(gl.BLEND_DST_ALPHA, 0)', 'gl.ZERO');
|
||||
shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_RGB, 1)', 'gl.FUNC_ADD');
|
||||
shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_ALPHA, 1)', 'gl.FUNC_SUBTRACT');
|
||||
shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_RGB, 1)', 'gl.SRC_ALPHA');
|
||||
shouldBe('gl.getIndexedParameter(gl.BLEND_DST_RGB, 1)', 'gl.ONE_MINUS_SRC_ALPHA');
|
||||
shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_ALPHA, 1)', 'gl.ZERO');
|
||||
shouldBe('gl.getIndexedParameter(gl.BLEND_DST_ALPHA, 1)', 'gl.ZERO');
|
||||
|
||||
shouldBe('gl.getIndexedParameter(gl.COLOR_WRITEMASK, 0)', '[false, false, false, false]');
|
||||
shouldBe('gl.getIndexedParameter(gl.COLOR_WRITEMASK, 1)', '[true, true, true, true]');
|
||||
|
||||
debug("Testing non-indexed getParamter get state from draw buffer 0");
|
||||
shouldBe('gl.getParameter(gl.BLEND_SRC_RGB)', 'gl.ONE');
|
||||
shouldBe('gl.getParameter(gl.BLEND_DST_RGB)', 'gl.ONE');
|
||||
shouldBe('gl.getParameter(gl.BLEND_SRC_ALPHA)', 'gl.ZERO');
|
||||
shouldBe('gl.getParameter(gl.BLEND_DST_ALPHA)', 'gl.ZERO');
|
||||
shouldBe('gl.getParameter(gl.BLEND_EQUATION_RGB)', 'gl.FUNC_ADD');
|
||||
shouldBe('gl.getParameter(gl.BLEND_EQUATION_ALPHA)', 'gl.FUNC_SUBTRACT');
|
||||
shouldBe('gl.getParameter(gl.COLOR_WRITEMASK)', '[false, false, false, false]');
|
||||
|
||||
debug("Testing non-indexed calls modify all draw buffers state");
|
||||
gl.blendEquationSeparate(gl.FUNC_SUBTRACT, gl.FUNC_ADD);
|
||||
gl.blendFuncSeparate(gl.ONE_MINUS_DST_ALPHA, gl.DST_ALPHA, gl.ONE, gl.ONE);
|
||||
gl.colorMask(true, false, true, false);
|
||||
wtu.glErrorShouldBe(gl, 0, 'Non-indexed state set without errors');
|
||||
|
||||
shouldBe('gl.getParameter(gl.BLEND_EQUATION_RGB)', 'gl.FUNC_SUBTRACT');
|
||||
shouldBe('gl.getParameter(gl.BLEND_EQUATION_ALPHA)', 'gl.FUNC_ADD');
|
||||
shouldBe('gl.getParameter(gl.BLEND_SRC_RGB)', 'gl.ONE_MINUS_DST_ALPHA');
|
||||
shouldBe('gl.getParameter(gl.BLEND_DST_RGB)', 'gl.DST_ALPHA');
|
||||
shouldBe('gl.getParameter(gl.BLEND_SRC_ALPHA)', 'gl.ONE');
|
||||
shouldBe('gl.getParameter(gl.BLEND_DST_ALPHA)', 'gl.ONE');
|
||||
shouldBe('gl.getParameter(gl.COLOR_WRITEMASK)', '[true, false, true, false]');
|
||||
|
||||
shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_RGB, 0)', 'gl.FUNC_SUBTRACT');
|
||||
shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_ALPHA, 0)', 'gl.FUNC_ADD');
|
||||
shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_RGB, 0)', 'gl.ONE_MINUS_DST_ALPHA');
|
||||
shouldBe('gl.getIndexedParameter(gl.BLEND_DST_RGB, 0)', 'gl.DST_ALPHA');
|
||||
shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_ALPHA, 0)', 'gl.ONE');
|
||||
shouldBe('gl.getIndexedParameter(gl.BLEND_DST_ALPHA, 0)', 'gl.ONE');
|
||||
shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_RGB, 1)', 'gl.FUNC_SUBTRACT');
|
||||
shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_ALPHA, 1)', 'gl.FUNC_ADD');
|
||||
shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_RGB, 1)', 'gl.ONE_MINUS_DST_ALPHA');
|
||||
shouldBe('gl.getIndexedParameter(gl.BLEND_DST_RGB, 1)', 'gl.DST_ALPHA');
|
||||
shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_ALPHA, 1)', 'gl.ONE');
|
||||
shouldBe('gl.getIndexedParameter(gl.BLEND_DST_ALPHA, 1)', 'gl.ONE');
|
||||
|
||||
shouldBe('gl.getIndexedParameter(gl.COLOR_WRITEMASK, 0)', '[true, false, true, false]');
|
||||
shouldBe('gl.getIndexedParameter(gl.COLOR_WRITEMASK, 1)', '[true, false, true, false]');
|
||||
}
|
||||
|
||||
function runTestExtension() {
|
||||
setup();
|
||||
|
||||
testInvalidValues();
|
||||
|
||||
enableDisableTest();
|
||||
|
||||
// blending should be enabled for drawBuffers 0 and 1 at this point
|
||||
|
||||
constantAlphaBlendColorValidationTest();
|
||||
|
||||
indexedBlendColorTest();
|
||||
|
||||
testColorMaskDrawNoOp();
|
||||
}
|
||||
|
||||
function runInvalidEnumsTest() {
|
||||
debug("Testing new enums for getIndexedParameterTest being invalid before requesting the extension");
|
||||
gl.getIndexedParameter(0x8009, 0); // BLEND_EQUATION_RGB
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'BLEND_EQUATION_RGB');
|
||||
gl.getIndexedParameter(0x883D, 0); // BLEND_EQUATION_ALPHA
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'BLEND_EQUATION_ALPHA');
|
||||
gl.getIndexedParameter(0x80C9, 0); // BLEND_SRC_RGB
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'BLEND_SRC_RGB');
|
||||
gl.getIndexedParameter(0x80CB, 0); // BLEND_SRC_ALPHA
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'BLEND_SRC_ALPHA');
|
||||
gl.getIndexedParameter(0x80C8, 0); // BLEND_DST_RGB
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'BLEND_DST_RGB');
|
||||
gl.getIndexedParameter(0x80CA, 0); // BLEND_DST_ALPHA
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'BLEND_DST_ALPHA');
|
||||
gl.getIndexedParameter(0x0C23, 0); // COLOR_WRITEMASK
|
||||
wtu.glErrorShouldBe(gl, [gl.INVALID_OPERATION, gl.INVALID_ENUM], 'invalid operations or invalid enums for COLOR_WRITEMASK');
|
||||
}
|
||||
|
||||
function testInvalidValues() {
|
||||
const numDrawBuffers = gl.getParameter(gl.MAX_DRAW_BUFFERS);
|
||||
if (!numDrawBuffers) throw new Error('!numDrawBuffers');
|
||||
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.enableiOES(gl.BLEND, -1)`);
|
||||
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.enableiOES(gl.BLEND, ${numDrawBuffers})`);
|
||||
wtu.shouldGenerateGLError(gl, 0, `ext.enableiOES(gl.BLEND, ${numDrawBuffers-1})`);
|
||||
|
||||
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.disableiOES(gl.BLEND, -1)`);
|
||||
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.disableiOES(gl.BLEND, ${numDrawBuffers})`);
|
||||
wtu.shouldGenerateGLError(gl, 0, `ext.disableiOES(gl.BLEND, ${numDrawBuffers-1})`);
|
||||
|
||||
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendEquationiOES(-1, gl.FUNC_ADD)`);
|
||||
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendEquationiOES(${numDrawBuffers}, gl.FUNC_ADD)`);
|
||||
wtu.shouldGenerateGLError(gl, 0, `ext.blendEquationiOES(${numDrawBuffers-1}, gl.FUNC_ADD)`);
|
||||
|
||||
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendEquationSeparateiOES(-1, gl.FUNC_ADD, gl.FUNC_ADD)`);
|
||||
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendEquationSeparateiOES(${numDrawBuffers}, gl.FUNC_ADD, gl.FUNC_ADD)`);
|
||||
wtu.shouldGenerateGLError(gl, 0, `ext.blendEquationSeparateiOES(${numDrawBuffers-1}, gl.FUNC_ADD, gl.FUNC_ADD)`);
|
||||
|
||||
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendFunciOES(-1, gl.ONE, gl.ONE)`);
|
||||
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendFunciOES(${numDrawBuffers}, gl.ONE, gl.ONE)`);
|
||||
wtu.shouldGenerateGLError(gl, 0, `ext.blendFunciOES(${numDrawBuffers-1}, gl.ONE, gl.ONE)`);
|
||||
|
||||
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendFuncSeparateiOES(-1, gl.ONE, gl.ZERO, gl.ONE, gl.ZERO)`);
|
||||
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendFuncSeparateiOES(${numDrawBuffers}, gl.ONE, gl.ZERO, gl.ONE, gl.ZERO)`);
|
||||
wtu.shouldGenerateGLError(gl, 0, `ext.blendFuncSeparateiOES(${numDrawBuffers-1}, gl.ONE, gl.ZERO, gl.ONE, gl.ZERO)`);
|
||||
|
||||
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.colorMaskiOES(-1, 1,1,1,1)`);
|
||||
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.colorMaskiOES(${numDrawBuffers}, 1,1,1,1)`);
|
||||
wtu.shouldGenerateGLError(gl, 0, `ext.colorMaskiOES(${numDrawBuffers-1}, 1,1,1,1)`);
|
||||
}
|
||||
|
||||
function* range(n) {
|
||||
for (let i = 0; i < n; i++) {
|
||||
yield i;
|
||||
}
|
||||
}
|
||||
|
||||
function testColorMaskDrawNoOp() {
|
||||
debug('');
|
||||
debug('testColorMaskDrawNoOp')
|
||||
// > If any draw buffer with an attachment does not have a defined
|
||||
// fragment shader output, draws generate INVALID_OPERATION,
|
||||
// unless all 4 channels of colorMask are set to false.
|
||||
const NUM_OUTPUTS = gl.getParameter(gl.MAX_COLOR_ATTACHMENTS);
|
||||
shouldBeTrue(`${NUM_OUTPUTS} > 1`);
|
||||
|
||||
const fb = gl.createFramebuffer();
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
|
||||
gl.viewport(0,0,1,1);
|
||||
|
||||
const DRAW_BUFFERS = [];
|
||||
for (const i of range(NUM_OUTPUTS)) {
|
||||
const tex = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex);
|
||||
gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, 1, 1);
|
||||
const ca = gl.COLOR_ATTACHMENT0+i;
|
||||
DRAW_BUFFERS.push(ca)
|
||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, ca,
|
||||
gl.TEXTURE_2D, tex, 0);
|
||||
}
|
||||
shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
|
||||
|
||||
gl.drawBuffers(DRAW_BUFFERS);
|
||||
console.log('DRAW_BUFFERS', DRAW_BUFFERS);
|
||||
|
||||
gl.clearColor(0, 0, 0, 0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
for (const i of range(NUM_OUTPUTS)) {
|
||||
gl.readBuffer(gl.COLOR_ATTACHMENT0+i);
|
||||
wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 0, 0], 'initially black');
|
||||
}
|
||||
|
||||
for (const validOutput of range(NUM_OUTPUTS)) {
|
||||
const invalidOutput = validOutput ^ 0b11;
|
||||
debug(`validOutput: ${validOutput}, invalidOutput: ${invalidOutput}`);
|
||||
const prog = wtu.setupProgram(gl, [
|
||||
`\
|
||||
#version 300 es
|
||||
void main() {
|
||||
gl_Position = vec4(0,0,0,1);
|
||||
gl_PointSize = 1.0f;
|
||||
}
|
||||
`,
|
||||
`\
|
||||
#version 300 es
|
||||
precision mediump float;
|
||||
layout(location=${validOutput}) out vec4 o_color;
|
||||
void main() {
|
||||
o_color = vec4(1,1,1,1);
|
||||
}
|
||||
`
|
||||
]);
|
||||
gl.useProgram(prog);
|
||||
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR,
|
||||
'After init.');
|
||||
|
||||
gl.colorMask(1,1,1,1);
|
||||
gl.drawBuffers(DRAW_BUFFERS);
|
||||
gl.drawArrays(gl.POINTS, 0, 1);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
|
||||
'Drawing with unmasked undefined color outputs.');
|
||||
|
||||
gl.colorMask(0,0,0,0);
|
||||
gl.drawBuffers(DRAW_BUFFERS);
|
||||
gl.drawArrays(gl.POINTS, 0, 1);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR,
|
||||
'Drawing with colorMask-masked-out undefined color outputs.');
|
||||
|
||||
gl.colorMask(1,1,1,1);
|
||||
gl.drawBuffers(DRAW_BUFFERS.map((x,i) => (i == invalidOutput) ? x : 0));
|
||||
gl.drawArrays(gl.POINTS, 0, 1);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
|
||||
'Drawing with wrong-id drawBuffer-masked-out undefined color outputs.');
|
||||
|
||||
gl.drawBuffers(DRAW_BUFFERS.map((x,i) => (i == validOutput) ? x : 0));
|
||||
gl.drawArrays(gl.POINTS, 0, 1);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR,
|
||||
'Drawing with drawBuffer-masked-out undefined color outputs.');
|
||||
|
||||
gl.colorMask(0,0,0,0);
|
||||
gl.drawBuffers([]);
|
||||
gl.drawArrays(gl.POINTS, 0, 1);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR,
|
||||
'Drawing with colorMask+drawBuffer-masked-out undefined color outputs.');
|
||||
|
||||
const testMask = (r,g,b,a) => {
|
||||
debug(`testMask(${[r,g,b,a]})`);
|
||||
gl.drawBuffers(DRAW_BUFFERS);
|
||||
|
||||
gl.colorMask(1,1,1,1);
|
||||
gl.clearColor(0, 0, 0, 0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
gl.colorMask(0,0,0,0);
|
||||
ext.colorMaskiOES(validOutput, r,g,b,a);
|
||||
gl.drawArrays(gl.POINTS, 0, 1);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR,
|
||||
`Drawing with sole defined color${validOutput} output writemask: ${[r,g,b,a]}.`);
|
||||
|
||||
for (const i of range(NUM_OUTPUTS)) {
|
||||
gl.readBuffer(gl.COLOR_ATTACHMENT0+i);
|
||||
let expect = [0,0,0,0];
|
||||
if (i == validOutput) {
|
||||
expect = [r,g,b,a].map(x => 0xff*x);
|
||||
}
|
||||
wtu.checkCanvasRect(gl, 0, 0, 1, 1, expect, `COLOR_ATTACHMENT${i}: [${expect}]`);
|
||||
}
|
||||
|
||||
gl.colorMask(1,1,1,1);
|
||||
gl.clearColor(0, 0, 0, 0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
gl.colorMask(r,g,b,a);
|
||||
for (const i of range(NUM_OUTPUTS)) {
|
||||
if (i == validOutput) continue;
|
||||
ext.colorMaskiOES(i, 0,0,0,0);
|
||||
}
|
||||
gl.drawArrays(gl.POINTS, 0, 1);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR,
|
||||
`Drawing with sole remaining defined color${validOutput} output writemask: ${[r,g,b,a]}.`);
|
||||
|
||||
for (const i of range(NUM_OUTPUTS)) {
|
||||
gl.readBuffer(gl.COLOR_ATTACHMENT0+i);
|
||||
let expect = [0,0,0,0];
|
||||
if (i == validOutput) {
|
||||
expect = [r,g,b,a].map(x => 0xff*x);
|
||||
}
|
||||
wtu.checkCanvasRect(gl, 0, 0, 1, 1, expect, `COLOR_ATTACHMENT${i}: [${expect}]`);
|
||||
}
|
||||
|
||||
if (r || g || b || a) {
|
||||
gl.colorMask(0,0,0,0);
|
||||
ext.colorMaskiOES(invalidOutput, r,g,b,a);
|
||||
gl.drawArrays(gl.POINTS, 0, 1);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
|
||||
`Drawing with wrong-id undefined color output color masked: ${[r,g,b,a]}.`);
|
||||
|
||||
gl.drawBuffers([]);
|
||||
gl.drawArrays(gl.POINTS, 0, 1);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR,
|
||||
'Drawing with wrong-id colorMask, but all-off drawBuffers.');
|
||||
|
||||
gl.drawBuffers(DRAW_BUFFERS.map((x,i) => (i == validOutput) ? x : 0));
|
||||
gl.drawArrays(gl.POINTS, 0, 1);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR,
|
||||
'Drawing with wrong-id colorMask, but right-id drawBuffers masked.');
|
||||
}
|
||||
};
|
||||
|
||||
testMask(0,0,0,0);
|
||||
testMask(1,0,0,0);
|
||||
testMask(0,1,0,0);
|
||||
testMask(0,0,1,0);
|
||||
testMask(0,0,0,1);
|
||||
testMask(1,1,1,1);
|
||||
}
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
if (!gl) {
|
||||
testFailed("context does not exist");
|
||||
} else {
|
||||
testPassed("context exists");
|
||||
|
||||
runInvalidEnumsTest();
|
||||
|
||||
ext = gl.getExtension("OES_draw_buffers_indexed");
|
||||
|
||||
wtu.runExtensionSupportedTest(gl, "OES_draw_buffers_indexed", ext !== null);
|
||||
|
||||
if (ext !== null) {
|
||||
runTestExtension();
|
||||
} else {
|
||||
testPassed("No OES_draw_buffers_indexed support -- this is legal");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
runTest();
|
||||
|
||||
var successfullyParsed = true;
|
||||
</script>
|
||||
<script src="../../js/js-test-post.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -38,7 +38,6 @@ var exts = gl.getSupportedExtensions();
|
||||
var promotedExtensions = [
|
||||
"ANGLE_instanced_arrays",
|
||||
"EXT_blend_minmax",
|
||||
"EXT_color_buffer_half_float",
|
||||
"EXT_frag_depth",
|
||||
"EXT_shader_texture_lod",
|
||||
"EXT_sRGB",
|
||||
|
@ -9,7 +9,7 @@
|
||||
<script src="../../js/webgl-test-utils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script id="vshaderIllegalBaseInstance" type="x-shader/x-vertex">#version 300 es
|
||||
<script id="vshaderBaseInstanceWithoutExt" type="x-shader/x-vertex">#version 300 es
|
||||
layout(location = 0) in vec2 vPosition;
|
||||
out vec4 color;
|
||||
void main()
|
||||
@ -18,20 +18,6 @@ void main()
|
||||
gl_Position = vec4(vPosition * 2.0 - 1.0, gl_BaseInstance, 1);
|
||||
}
|
||||
</script>
|
||||
<script id="vshaderBaseInstanceZero" type="x-shader/x-vertex">#version 300 es
|
||||
#extension GL_ANGLE_base_vertex_base_instance : require
|
||||
layout(location = 0) in vec2 vPosition;
|
||||
out vec4 color;
|
||||
void main()
|
||||
{
|
||||
if (gl_BaseInstance == 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>
|
||||
<!-- Check gl_InstanceID starts at 0 regardless of gl_BaseInstance -->
|
||||
<script id="vshaderInstanceIDCheck" type="x-shader/x-vertex">#version 300 es
|
||||
layout(location = 0) in vec2 vPosition;
|
||||
@ -46,7 +32,7 @@ void main()
|
||||
gl_Position = vec4(vPosition * 2.0 - 1.0, 0, 1);
|
||||
}
|
||||
</script>
|
||||
<script id="vshaderIllegalBaseVertex" type="x-shader/x-vertex">#version 300 es
|
||||
<script id="vshaderBaseVertexWithoutExt" type="x-shader/x-vertex">#version 300 es
|
||||
layout(location = 0) in vec2 vPosition;
|
||||
out vec4 color;
|
||||
void main()
|
||||
@ -55,17 +41,13 @@ void main()
|
||||
gl_Position = vec4(vPosition * 2.0 - 1.0, gl_BaseVertex, 1);
|
||||
}
|
||||
</script>
|
||||
<script id="vshaderBaseVertexZero" type="x-shader/x-vertex">#version 300 es
|
||||
<script id="vshaderWithExt" type="x-shader/x-vertex">#version 300 es
|
||||
#extension GL_ANGLE_base_vertex_base_instance : require
|
||||
layout(location = 0) in vec2 vPosition;
|
||||
out vec4 color;
|
||||
void main()
|
||||
{
|
||||
if (gl_BaseVertex == 0) {
|
||||
color = vec4(0, 1, 0, 1);
|
||||
} else {
|
||||
color = vec4(1, 0, 0, 1);
|
||||
}
|
||||
color = vec4(0, 1, 0, 1);
|
||||
gl_Position = vec4(vPosition * 2.0 - 1.0, 0, 1);
|
||||
}
|
||||
</script>
|
||||
@ -84,7 +66,6 @@ void main()
|
||||
}
|
||||
</script>
|
||||
<script id="vshaderSimple" type="x-shader/x-vertex">#version 300 es
|
||||
#extension GL_ANGLE_base_vertex_base_instance : require
|
||||
layout(location = 0) in vec2 vPosition;
|
||||
layout(location = 1) in float vInstance;
|
||||
out vec4 color;
|
||||
@ -121,7 +102,13 @@ description("This test verifies the functionality of the WEBGL_[multi]_draw_base
|
||||
|
||||
const wtu = WebGLTestUtils;
|
||||
const canvas = document.getElementById("canvas");
|
||||
const gl = wtu.create3DContext(canvas, null, 2);
|
||||
canvas.style.backgroundColor = '#000';
|
||||
canvas.style.imageRendering = 'pixelated'; // Because Chrome doesn't support crisp-edges.
|
||||
canvas.style.imageRendering = 'crisp-edges';
|
||||
const attribs = {
|
||||
antialias: false,
|
||||
};
|
||||
const gl = wtu.create3DContext(canvas, attribs, 2);
|
||||
|
||||
const width = gl.canvas.width;
|
||||
const height = gl.canvas.height;
|
||||
@ -133,6 +120,7 @@ const tileSize = [ 1/x_count, 1/y_count ];
|
||||
const tilePixelSize = [ Math.floor(width / x_count), Math.floor(height / y_count) ];
|
||||
const quadRadius = [ 0.25 * tileSize[0], 0.25 * tileSize[1] ];
|
||||
const pixelCheckSize = [ Math.floor(quadRadius[0] * width), Math.floor(quadRadius[1] * height) ];
|
||||
const bufferUsageSet = [ gl.STATIC_DRAW, gl.DYNAMIC_DRAW ];
|
||||
|
||||
function getTileCenter(x, y) {
|
||||
return [ tileSize[0] * (0.5 + x), tileSize[1] * (0.5 + y) ];
|
||||
@ -193,18 +181,6 @@ const vertexBuffer = gl.createBuffer();
|
||||
const nonIndexedVertexBuffer = gl.createBuffer();
|
||||
const instanceIDBuffer = gl.createBuffer();
|
||||
|
||||
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, nonIndexedVertexBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, nonIndexedVertices, gl.STATIC_DRAW);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, instanceIDBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, instanceIDs, gl.STATIC_DRAW);
|
||||
|
||||
const drawArraysDrawCount = x_count / 2;
|
||||
let drawArraysParams = {
|
||||
drawCount: drawArraysDrawCount,
|
||||
@ -237,6 +213,20 @@ for (let v = 0; v < y_count; ++v) {
|
||||
}
|
||||
}
|
||||
|
||||
function setupGeneralBuffers(bufferUsage) {
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, vertices, bufferUsage);
|
||||
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
|
||||
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, bufferUsage);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, nonIndexedVertexBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, nonIndexedVertices, bufferUsage);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, instanceIDBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, instanceIDs, bufferUsage);
|
||||
}
|
||||
|
||||
// Check if the extension is either both enabled and supported or
|
||||
// not enabled and not supported.
|
||||
function runSupportedTest(extensionName, extensionEnabled) {
|
||||
@ -267,8 +257,245 @@ function runTest() {
|
||||
|
||||
doTest('WEBGL_draw_instanced_base_vertex_base_instance', false);
|
||||
doTest('WEBGL_multi_draw_instanced_base_vertex_base_instance', true);
|
||||
|
||||
testGlslBuiltins();
|
||||
}
|
||||
|
||||
// -
|
||||
|
||||
function* range(n) {
|
||||
for (let i = 0; i < n; i++) {
|
||||
yield i;
|
||||
}
|
||||
}
|
||||
|
||||
function crossCombine(...args) {
|
||||
function crossCombine2(listA, listB) {
|
||||
const listC = [];
|
||||
for (const a of listA) {
|
||||
for (const b of listB) {
|
||||
const c = Object.assign({}, a, b);
|
||||
listC.push(c);
|
||||
}
|
||||
}
|
||||
return listC;
|
||||
}
|
||||
|
||||
let res = [{}];
|
||||
while (args.length) {
|
||||
const next = args.shift();
|
||||
next[0].defined;
|
||||
res = crossCombine2(res, next);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// -
|
||||
|
||||
const PASSTHROUGH_FRAG_SRC = `\
|
||||
#version 300 es
|
||||
precision mediump float;
|
||||
in vec4 v_color;
|
||||
out vec4 o_color;
|
||||
|
||||
void main() {
|
||||
o_color = v_color;
|
||||
}
|
||||
`;
|
||||
|
||||
function testGlslBuiltins() {
|
||||
const EXT = gl.getExtension('WEBGL_draw_instanced_base_vertex_base_instance');
|
||||
|
||||
const vertid_prog = (() => {
|
||||
const vert_src = `\
|
||||
#version 300 es
|
||||
#line 405
|
||||
layout(location = 0) in int a_vertex_id; // Same as first_vert+gl_VertexID
|
||||
out vec4 v_color;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(0,0,0,1);
|
||||
gl_PointSize = 1.0;
|
||||
v_color = vec4(float(gl_VertexID), float(a_vertex_id),0,0);
|
||||
v_color /= 255.0;
|
||||
}
|
||||
`;
|
||||
const prog = wtu.setupProgram(gl, [vert_src, PASSTHROUGH_FRAG_SRC],
|
||||
undefined, undefined, /*logShaders*/ true);
|
||||
expectTrue(!!prog, `make_vertid_prog failed`);
|
||||
return prog;
|
||||
})();
|
||||
|
||||
const instid_prog = (() => {
|
||||
const vert_src = `\
|
||||
#version 300 es
|
||||
#line 425
|
||||
layout(location = 0) in int a_vertex_id; // Same as first_vert+gl_VertexID
|
||||
layout(location = 1) in int a_instance_div1; // Same as base_instance+gl_InstanceID
|
||||
layout(location = 2) in int a_instance_div2; // Same as base_instance+floor(gl_InstanceID/2)
|
||||
layout(location = 3) in int a_instance_div3; // Same as base_instance+floor(gl_InstanceID/3)
|
||||
out vec4 v_color;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(0,0,0,1);
|
||||
gl_PointSize = 1.0;
|
||||
v_color = vec4(float(gl_InstanceID), float(a_instance_div1),
|
||||
float(a_instance_div2), float(a_instance_div3));
|
||||
v_color /= 255.0;
|
||||
}
|
||||
`;
|
||||
const prog = wtu.setupProgram(gl, [vert_src, PASSTHROUGH_FRAG_SRC],
|
||||
undefined, undefined, /*logShaders*/ true);
|
||||
expectTrue(!!prog, `make_instid_prog failed`);
|
||||
return prog;
|
||||
})();
|
||||
|
||||
const COUNT_UP_DATA = new Int32Array(1000);
|
||||
for (const i in COUNT_UP_DATA) {
|
||||
COUNT_UP_DATA[i] = i;
|
||||
}
|
||||
|
||||
const vertex_id_buf = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_id_buf);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, COUNT_UP_DATA, gl.STATIC_DRAW);
|
||||
gl.enableVertexAttribArray(0);
|
||||
gl.vertexAttribIPointer(0, 1, gl.INT, 0, 0);
|
||||
|
||||
gl.enableVertexAttribArray(1);
|
||||
gl.vertexAttribIPointer(1, 1, gl.INT, 0, 0);
|
||||
gl.vertexAttribDivisor(1, 1);
|
||||
|
||||
gl.enableVertexAttribArray(2);
|
||||
gl.vertexAttribIPointer(2, 1, gl.INT, 0, 0);
|
||||
gl.vertexAttribDivisor(2, 2);
|
||||
|
||||
gl.enableVertexAttribArray(3);
|
||||
gl.vertexAttribIPointer(3, 1, gl.INT, 0, 0);
|
||||
gl.vertexAttribDivisor(3, 3);
|
||||
|
||||
const index_buf = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buf);
|
||||
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, COUNT_UP_DATA, gl.STATIC_DRAW);
|
||||
|
||||
gl.canvas.width = gl.canvas.height = 1;
|
||||
gl.canvas.style.width = gl.canvas.style.height = '1em';
|
||||
gl.viewport(0, 0, 1, 1);
|
||||
|
||||
const expect_pixel = (() => {
|
||||
const was = new Uint8Array(4);
|
||||
return (desc, subtest, expected) => {
|
||||
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, was);
|
||||
if (!areArraysEqual(was, expected)) {
|
||||
testFailed(`${subtest}: Expected [${expected}], was [${was}]. desc: ${JSON.stringify(desc)}`);
|
||||
} else {
|
||||
debug(`${subtest}: Was [${was}] as expected.`);
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
// Common setup complete
|
||||
// -
|
||||
// Create testcases
|
||||
|
||||
const DRAW_FUNC_COMBINER = [{
|
||||
name: 'drawArraysInstanced',
|
||||
draw: desc => {
|
||||
if (desc.base_vert) return false;
|
||||
if (desc.base_inst) return false;
|
||||
gl.drawArraysInstanced(gl[desc.mode], desc.first_vert,
|
||||
desc.vert_count, desc.inst_count);
|
||||
return true;
|
||||
},
|
||||
}, {
|
||||
name: 'drawElementsInstanced',
|
||||
draw: desc => {
|
||||
if (desc.base_vert) return false;
|
||||
if (desc.base_inst) return false;
|
||||
gl.drawElementsInstanced(gl[desc.mode], desc.vert_count,
|
||||
gl.UNSIGNED_INT, 4*desc.first_vert, desc.inst_count);
|
||||
return true;
|
||||
},
|
||||
}, {
|
||||
name: 'drawArraysInstancedBaseInstanceWEBGL',
|
||||
draw: desc => {
|
||||
if (desc.base_vert) return false;
|
||||
if (!EXT) return false;
|
||||
EXT.drawArraysInstancedBaseInstanceWEBGL(gl[desc.mode],
|
||||
desc.first_vert, desc.vert_count, desc.inst_count,
|
||||
desc.base_inst);
|
||||
return true;
|
||||
},
|
||||
}, {
|
||||
name: 'drawElementsInstancedBaseVertexBaseInstanceWEBGL',
|
||||
draw: desc => {
|
||||
if (!EXT) return false;
|
||||
EXT.drawElementsInstancedBaseVertexBaseInstanceWEBGL(
|
||||
gl[desc.mode], desc.vert_count, gl.UNSIGNED_INT, 4*desc.first_vert,
|
||||
desc.inst_count, desc.base_vert, desc.base_inst);
|
||||
return true;
|
||||
},
|
||||
}];
|
||||
|
||||
// -
|
||||
|
||||
function make_key_combiner(key, vals) {
|
||||
const ret = [];
|
||||
for (const v of vals) {
|
||||
const cur = {};
|
||||
cur[key] = v;
|
||||
ret.push(cur);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
const TEST_DESCS = crossCombine(
|
||||
DRAW_FUNC_COMBINER,
|
||||
make_key_combiner('base_vert', [0,1,2]),
|
||||
make_key_combiner('vert_count', [0,1,2]),
|
||||
make_key_combiner('base_inst', [0,1,2]),
|
||||
make_key_combiner('inst_count', range(10)),
|
||||
make_key_combiner('first_vert', [0,1,2]),
|
||||
);
|
||||
console.log('TEST_DESCS', TEST_DESCS);
|
||||
|
||||
// -
|
||||
// Run testcases
|
||||
|
||||
gl.disable(gl.DEPTH_TEST);
|
||||
gl.disable(gl.STENCIL_TEST);
|
||||
gl.disable(gl.BLEND);
|
||||
|
||||
for (const desc of TEST_DESCS) {
|
||||
gl.disable(gl.SCISSOR_TEST);
|
||||
gl.clearBufferfv(gl.COLOR, 0, [1,0,0,1]);
|
||||
|
||||
const last_gl_vert_id = desc.base_vert + desc.vert_count - 1;
|
||||
const last_vert_id = desc.first_vert + last_gl_vert_id;
|
||||
const last_inst_id = desc.inst_count - 1;
|
||||
const last_inst_div1 = desc.base_inst + last_inst_id;
|
||||
const last_inst_div2 = desc.base_inst + Math.floor(last_inst_id / 2);
|
||||
const last_inst_div3 = desc.base_inst + Math.floor(last_inst_id / 3);
|
||||
|
||||
gl.useProgram(vertid_prog);
|
||||
if (!desc.draw(desc)) continue;
|
||||
debug('\ndesc: ' + JSON.stringify(desc));
|
||||
|
||||
wtu.glErrorAssert(gl, 0);
|
||||
if (!desc.vert_count || !desc.inst_count) {
|
||||
expect_pixel(desc, 'vertid_prog', [255, 0, 0, 255]);
|
||||
continue;
|
||||
}
|
||||
|
||||
expect_pixel(desc, 'vertid_prog', [last_gl_vert_id, last_vert_id, 0, 0]);
|
||||
|
||||
gl.useProgram(instid_prog);
|
||||
desc.draw(desc);
|
||||
expect_pixel(desc, 'instid_prog', [last_inst_id, last_inst_div1, last_inst_div2, last_inst_div3]);
|
||||
}
|
||||
}
|
||||
|
||||
// -
|
||||
|
||||
function doTest(extensionName, multiDraw) {
|
||||
const ext = gl.getExtension(extensionName);
|
||||
if (!runSupportedTest(extensionName, ext)) {
|
||||
@ -279,21 +506,20 @@ function doTest(extensionName, multiDraw) {
|
||||
const vs = [
|
||||
'#version 300 es',
|
||||
config.isMultiDraw ? '#extension GL_ANGLE_multi_draw : require' : '',
|
||||
'#extension GL_ANGLE_base_vertex_base_instance : require',
|
||||
//'#extension GL_ANGLE_base_vertex_base_instance : require',
|
||||
'#define kCountX ' + countX.toString(),
|
||||
'#define kCountY ' + countY.toString(),
|
||||
'layout(location = 0) in vec2 vPosition;',
|
||||
config.useBaseInstanceBuiltin ? '' : 'layout(location = 1) in float vInstanceID;',
|
||||
'layout(location = 1) in float vInstanceID;',
|
||||
'out vec4 color;',
|
||||
'void main()',
|
||||
'{',
|
||||
' const float xStep = 1.0 / float(kCountX);',
|
||||
' const float yStep = 1.0 / float(kCountY);',
|
||||
' float xID = ' + (config.useBaseInstanceBuiltin ? 'float(gl_InstanceID + gl_BaseInstance)' : 'vInstanceID') + ';',
|
||||
' float xID = vInstanceID;',
|
||||
' float xColor = 1.0 - xStep * xID;',
|
||||
' float yID = floor(float(gl_VertexID) / ' + (config.isDrawArrays ? '6.0' : '4.0') + ' + 0.01);',
|
||||
' color = vec4(xColor, 1.0 - yStep * yID, ',
|
||||
config.useBaseVertexBuiltin ? '1.0 - yStep * float(gl_BaseVertex) / 4.0' : '1.0',
|
||||
' color = vec4(xColor, 1.0 - yStep * yID, 1.0',
|
||||
' , 1.0);',
|
||||
' mat3 transform = mat3(1.0);',
|
||||
' transform[2][0] = xID * xStep;',
|
||||
@ -306,20 +532,20 @@ function doTest(extensionName, multiDraw) {
|
||||
return [vs, fs];
|
||||
}
|
||||
|
||||
function runValidationTests() {
|
||||
function runValidationTests(bufferUsage) {
|
||||
const vertexBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0.2,0.2, 0.8,0.2, 0.5,0.8 ]), gl.STATIC_DRAW);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0.2,0.2, 0.8,0.2, 0.5,0.8 ]), bufferUsage);
|
||||
|
||||
const indexBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
|
||||
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array([ 0, 1, 2 ]), gl.STATIC_DRAW);
|
||||
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array([ 0, 1, 2 ]), bufferUsage);
|
||||
|
||||
const instanceBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, instanceBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0, 1, 2 ]), gl.STATIC_DRAW);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0, 1, 2 ]), bufferUsage);
|
||||
|
||||
const program = wtu.setupProgram(gl, ['vshaderSimple', 'fshader'], ['vPosition, vInstanceID'], [0, 1]);
|
||||
const program = wtu.setupProgram(gl, ['vshaderSimple', 'fshader'], ['vPosition, vInstanceID'], [0, 1], true);
|
||||
expectTrue(program != null, "can compile simple program");
|
||||
|
||||
function setupInstanced() {
|
||||
@ -486,39 +712,28 @@ function doTest(extensionName, multiDraw) {
|
||||
}
|
||||
}
|
||||
|
||||
function runShaderTests() {
|
||||
const illegalBaseInstanceProgram = wtu.setupProgram(gl, ["vshaderIllegalBaseInstance", "fshader"]);
|
||||
expectTrue(illegalBaseInstanceProgram == null, "cannot compile program with gl_BaseInstance but no extension directive");
|
||||
const illegalBaseVertexProgram = wtu.setupProgram(gl, ["vshaderIllegalBaseVertex", "fshader"]);
|
||||
expectTrue(illegalBaseVertexProgram == null, "cannot compile program with gl_BaseVertex but no extension directive");
|
||||
function runShaderTests(bufferUsage) {
|
||||
let badProgram;
|
||||
|
||||
badProgram = wtu.setupProgram(gl, ["vshaderBaseInstanceWithoutExt", "fshader"]);
|
||||
expectTrue(!badProgram, "cannot compile program with gl_BaseInstance but no extension directive");
|
||||
badProgram = wtu.setupProgram(gl, ["vshaderBaseVertexWithoutExt", "fshader"]);
|
||||
expectTrue(!badProgram, "cannot compile program with gl_BaseVertex but no extension directive");
|
||||
|
||||
badProgram = wtu.setupProgram(gl, ["vshaderWithExt", "fshader"]);
|
||||
expectTrue(!badProgram, "cannot compile program with #extension GL_ANGLE_base_vertex_base_instance");
|
||||
|
||||
const x = Math.floor(width * 0.4);
|
||||
const y = Math.floor(height * 0.4);
|
||||
const xSize = Math.floor(width * 0.2);
|
||||
const ySize = Math.floor(height * 0.2);
|
||||
|
||||
// gl_BaseInstance and gl_InstanceID
|
||||
// gl_InstanceID
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0, 1,0, 0.5,1, 0,1, 0.5,0, 1,1 ]), gl.STATIC_DRAW);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0, 1,0, 0.5,1, 0,1, 0.5,0, 1,1 ]), bufferUsage);
|
||||
gl.enableVertexAttribArray(0);
|
||||
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
|
||||
|
||||
const baseInstanceZeroProgram = wtu.setupProgram(gl, ["vshaderBaseInstanceZero", "fshader"], ["vPosition"], [0]);
|
||||
expectTrue(baseInstanceZeroProgram !== null, "can compile program with gl_BaseInstance");
|
||||
gl.useProgram(baseInstanceZeroProgram);
|
||||
|
||||
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||||
if (!multiDraw) {
|
||||
ext.drawArraysInstancedBaseInstanceWEBGL(gl.TRIANGLES, 0, 6, 1, 5);
|
||||
} else {
|
||||
ext.multiDrawArraysInstancedBaseInstanceWEBGL(gl.TRIANGLES, [0], 0, [6], 0, [1], 0, [5], 0, 1);
|
||||
}
|
||||
|
||||
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||||
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
||||
|
||||
wtu.checkCanvasRect(gl, x, y, xSize, ySize, [0, 255, 0, 255], "gl_BaseInstance is 0 for non-BaseInstance draw calls");
|
||||
|
||||
const instanceIDProgram = wtu.setupProgram(gl, ["vshaderInstanceIDCheck", "fshader"], ["vPosition"], [0]);
|
||||
expectTrue(instanceIDProgram !== null, "can compile program with gl_InstanceID");
|
||||
gl.useProgram(instanceIDProgram);
|
||||
@ -532,30 +747,14 @@ function doTest(extensionName, multiDraw) {
|
||||
|
||||
wtu.checkCanvasRect(gl, x, y, xSize, ySize, [0, 255, 0, 255], "gl_InstanceID should always starts from 0");
|
||||
|
||||
// gl_BaseVertex and gl_VertexID
|
||||
// gl_VertexID
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0, 1,0, 0.5,1, 0,1, 0.5,0, 1,1, 0,0, 1,0, 0.5,1, 0,1 ]), gl.STATIC_DRAW);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0, 1,0, 0.5,1, 0,1, 0.5,0, 1,1, 0,0, 1,0, 0.5,1, 0,1 ]), bufferUsage);
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.createBuffer());
|
||||
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array([0, 1, 2, 3, 4, 5]), gl.STATIC_DRAW);
|
||||
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array([0, 1, 2, 3, 4, 5]), bufferUsage);
|
||||
gl.enableVertexAttribArray(0);
|
||||
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
|
||||
|
||||
const baseVertexZeroProgram = wtu.setupProgram(gl, ["vshaderBaseVertexZero", "fshader"], ["vPosition"], [0]);
|
||||
expectTrue(baseVertexZeroProgram !== null, "can compile program with gl_BaseVertex");
|
||||
gl.useProgram(baseVertexZeroProgram);
|
||||
|
||||
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||||
if (!multiDraw) {
|
||||
ext.drawElementsInstancedBaseVertexBaseInstanceWEBGL(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0, 1, 3, 0);
|
||||
} else {
|
||||
ext.multiDrawElementsInstancedBaseVertexBaseInstanceWEBGL(gl.TRIANGLES, [6], 0, gl.UNSIGNED_BYTE, [0], 0, [1], 0, [3], 0, [0], 0, 1);
|
||||
}
|
||||
|
||||
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||||
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0);
|
||||
|
||||
wtu.checkCanvasRect(gl, x, y, xSize, ySize, [0, 255, 0, 255], "gl_BaseVertex is 0 for non-BaseVertex draw calls");
|
||||
|
||||
const vertexIDProgram = wtu.setupProgram(gl, ["vshaderVertexIDCheck", "fshader"], ["vPosition"], [0]);
|
||||
expectTrue(vertexIDProgram !== null, "can compile program with gl_VertexID");
|
||||
gl.useProgram(vertexIDProgram);
|
||||
@ -674,30 +873,6 @@ function doTest(extensionName, multiDraw) {
|
||||
useBaseInstanceBuiltin: false
|
||||
});
|
||||
|
||||
checkDraw({
|
||||
drawFunc: multiDraw ? multiDrawArraysInstancedBaseInstance : drawArraysInstancedBaseInstance,
|
||||
isDrawArrays: true,
|
||||
isMultiDraw: multiDraw,
|
||||
useBaseVertexBuiltin: true,
|
||||
useBaseInstanceBuiltin: false
|
||||
});
|
||||
|
||||
checkDraw({
|
||||
drawFunc: multiDraw ? multiDrawArraysInstancedBaseInstance : drawArraysInstancedBaseInstance,
|
||||
isDrawArrays: true,
|
||||
isMultiDraw: multiDraw,
|
||||
useBaseVertexBuiltin: false,
|
||||
useBaseInstanceBuiltin: true
|
||||
});
|
||||
|
||||
checkDraw({
|
||||
drawFunc: multiDraw ? multiDrawArraysInstancedBaseInstance : drawArraysInstancedBaseInstance,
|
||||
isDrawArrays: true,
|
||||
isMultiDraw: multiDraw,
|
||||
useBaseVertexBuiltin: true,
|
||||
useBaseInstanceBuiltin: true
|
||||
});
|
||||
|
||||
checkDraw({
|
||||
drawFunc: multiDraw ? multiDrawElementsInstancedBaseVertexBaseInstance : drawElementsInstancedBaseVertexBaseInstance,
|
||||
isDrawArrays: false,
|
||||
@ -705,35 +880,16 @@ function doTest(extensionName, multiDraw) {
|
||||
useBaseVertexBuiltin: false,
|
||||
useBaseInstanceBuiltin: false
|
||||
});
|
||||
|
||||
checkDraw({
|
||||
drawFunc: multiDraw ? multiDrawElementsInstancedBaseVertexBaseInstance : drawElementsInstancedBaseVertexBaseInstance,
|
||||
isDrawArrays: false,
|
||||
isMultiDraw: multiDraw,
|
||||
useBaseVertexBuiltin: true,
|
||||
useBaseInstanceBuiltin: false
|
||||
});
|
||||
|
||||
checkDraw({
|
||||
drawFunc: multiDraw ? multiDrawElementsInstancedBaseVertexBaseInstance : drawElementsInstancedBaseVertexBaseInstance,
|
||||
isDrawArrays: false,
|
||||
isMultiDraw: multiDraw,
|
||||
useBaseVertexBuiltin: false,
|
||||
useBaseInstanceBuiltin: true
|
||||
});
|
||||
|
||||
checkDraw({
|
||||
drawFunc: multiDraw ? multiDrawElementsInstancedBaseVertexBaseInstance : drawElementsInstancedBaseVertexBaseInstance,
|
||||
isDrawArrays: false,
|
||||
isMultiDraw: multiDraw,
|
||||
useBaseVertexBuiltin: true,
|
||||
useBaseInstanceBuiltin: true
|
||||
});
|
||||
}
|
||||
|
||||
runValidationTests();
|
||||
runShaderTests();
|
||||
runPixelTests();
|
||||
for (let i = 0; i < bufferUsageSet.length; i++) {
|
||||
let bufferUsage = bufferUsageSet[i];
|
||||
debug("Testing with BufferUsage = " + bufferUsage);
|
||||
setupGeneralBuffers(bufferUsage);
|
||||
runValidationTests(bufferUsage);
|
||||
runShaderTests(bufferUsage);
|
||||
runPixelTests();
|
||||
}
|
||||
}
|
||||
|
||||
runTest();
|
||||
|
@ -17,6 +17,7 @@ const-array-init.html
|
||||
forbidden-operators.html
|
||||
--min-version 2.0.1 forward-declaration.html
|
||||
frag-depth.html
|
||||
--min-version 2.0.1 fragment-shader-loop-crash.html
|
||||
--min-version 2.0.1 gradient-in-discontinuous-loop.html
|
||||
--min-version 2.0.1 input-with-interpotaion-as-lvalue.html
|
||||
invalid-default-precision.html
|
||||
@ -26,6 +27,8 @@ loops-with-side-effects.html
|
||||
--min-version 2.0.1 matrix-row-major-dynamic-indexing.html
|
||||
misplaced-version-directive.html
|
||||
--min-version 2.0.1 no-attribute-vertex-shader.html
|
||||
--min-version 2.0.1 precision-side-effects-bug.html
|
||||
--min-version 2.0.1 reciprocal-sqrt-of-sum-of-squares-crash.html
|
||||
sampler-no-precision.html
|
||||
--min-version 2.0.1 sampler-array-indexing.html
|
||||
sequence-operator-returns-non-constant.html
|
||||
@ -42,6 +45,7 @@ short-circuiting-in-loop-condition.html
|
||||
texture-offset-out-of-range.html
|
||||
--min-version 2.0.1 texture-offset-uniform-texture-coordinate.html
|
||||
--min-version 2.0.1 tricky-loop-conditions.html
|
||||
--min-version 2.0.1 uint-int-shift-bug.html
|
||||
--min-version 2.0.1 unary-minus-operator-in-dynamic-loop.html
|
||||
uniform-block-layouts.html
|
||||
uniform-block-layout-match.html
|
||||
|
@ -0,0 +1,72 @@
|
||||
<!--
|
||||
Copyright (c) 2021 The Khronos Group Inc.
|
||||
Use of this source code is governed by an MIT-style license that can be
|
||||
found in the LICENSE.txt file.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Fragment shader containing loop should not crash</title>
|
||||
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
|
||||
<link rel="stylesheet" href="../../resources/glsl-feature-tests.css"/>
|
||||
<script src="../../js/js-test-pre.js"></script>
|
||||
<script src="../../js/webgl-test-utils.js"></script>
|
||||
<script src="../../js/glsl-conformance-test.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<script id="vshader" type="x-shader/x-vertex">#version 300 es
|
||||
precision highp float;
|
||||
out vec2 v_tex_coord;
|
||||
uniform mat4 matrix;
|
||||
|
||||
void main() {
|
||||
v_tex_coord = vec2(0.0, 0.0);
|
||||
gl_Position = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
</script>
|
||||
<script id="fshader" type="x-shader/x-fragment">#version 300 es
|
||||
precision highp float;
|
||||
|
||||
in vec2 v_tex_coord;
|
||||
out vec4 out_color;
|
||||
|
||||
uniform sampler2D texture_1;
|
||||
uniform vec2 resolution;
|
||||
|
||||
vec4 do_loops(vec4 z)
|
||||
{
|
||||
vec4 v[16];
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
v[i] = z;
|
||||
}
|
||||
return v[1];
|
||||
}
|
||||
|
||||
void main() {
|
||||
out_color = do_loops(vec4(0.2, 0.4, 0.6, 1.0)) - texture(texture_1, v_tex_coord);
|
||||
}
|
||||
</script>
|
||||
<script type="application/javascript">
|
||||
"use strict";
|
||||
description();
|
||||
const wtu = WebGLTestUtils;
|
||||
const tests = [
|
||||
{
|
||||
vShaderSource: wtu.getScript('vshader'),
|
||||
fShaderSource: wtu.getScript('fshader'),
|
||||
vShaderSuccess: true,
|
||||
fShaderSuccess: true,
|
||||
linkSuccess: true,
|
||||
passMsg: 'Fragment shader containing a simple loop should compile and link'
|
||||
}
|
||||
];
|
||||
|
||||
GLSLConformanceTester.runTests(tests, 2);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,125 @@
|
||||
<!--
|
||||
Copyright (c) 2020 The Khronos Group Inc.
|
||||
Use of this source code is governed by an MIT-style license that can be
|
||||
found in the LICENSE.txt file.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Verify precision side effects (Adreno driver bug)</title>
|
||||
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
|
||||
<script src="../../js/js-test-pre.js"></script>
|
||||
<script src="../../js/webgl-test-utils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="canvas" width="2" height="2"> </canvas>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
|
||||
<script id="vshader-simple" type="x-shader/x-vertex">#version 300 es
|
||||
in vec3 aPosition;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(aPosition, 1.0);
|
||||
}
|
||||
</script>
|
||||
<script id="fshader-int" type="x-shader/x-fragment">#version 300 es
|
||||
out highp vec4 myFragColor;
|
||||
void main() {
|
||||
highp int t;
|
||||
t = 0 | (int(t == t) * 0x8000);
|
||||
|
||||
if (t == 0x8000)
|
||||
myFragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
else
|
||||
myFragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
</script>
|
||||
<script id="fshader-ivec2" type="x-shader/x-fragment">#version 300 es
|
||||
out highp vec4 myFragColor;
|
||||
void main() {
|
||||
highp ivec2 t;
|
||||
t = 0 | (ivec2(t == t) * 0x8000);
|
||||
|
||||
if (t == ivec2(0x8000))
|
||||
myFragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
else
|
||||
myFragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
</script>
|
||||
<script id="fshader-ivec3" type="x-shader/x-fragment">#version 300 es
|
||||
out highp vec4 myFragColor;
|
||||
void main() {
|
||||
highp ivec3 t;
|
||||
t = 0 | (ivec3(t == t) * 0x8000);
|
||||
|
||||
if (t == ivec3(0x8000))
|
||||
myFragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
else
|
||||
myFragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
</script>
|
||||
<script id="fshader-ivec4" type="x-shader/x-fragment">#version 300 es
|
||||
out highp vec4 myFragColor;
|
||||
void main() {
|
||||
highp ivec4 t;
|
||||
t = 0 | (ivec4(t == t) * 0x8000);
|
||||
|
||||
if (t == ivec4(0x8000))
|
||||
myFragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
else
|
||||
myFragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
</script>
|
||||
<script type="application/javascript">
|
||||
"use strict";
|
||||
description("Verify precision side effects");
|
||||
debug("");
|
||||
debug("When this test is run on Adreno (no repros on other vendors so far):");
|
||||
debug(" - the result of the expression 0 | (int(e0 == e0) * 0x8000) somehow returns -32768 instead of 32768 despite the variable using highp precision;");
|
||||
debug(" - splitting the expression along | fixes the issue (could also be observed with other operators).");
|
||||
debug('For additional reference see this <a href="https://github.com/KhronosGroup/WebGL/pull/3192">pull request</a> and <a href="http://crbug.com/1155942">Chromium bug</a>');
|
||||
debug("");
|
||||
var wtu = WebGLTestUtils;
|
||||
function test() {
|
||||
var gl = wtu.create3DContext("canvas", undefined, 2);
|
||||
if (!gl) {
|
||||
testFailed("context does not exist");
|
||||
return;
|
||||
}
|
||||
wtu.setupUnitQuad(gl);
|
||||
|
||||
var testCases = [
|
||||
{ vshader: "vshader-simple", fshader: "fshader-int", desc: "fragment shader int" },
|
||||
{ vshader: "vshader-simple", fshader: "fshader-ivec2", desc: "fragment shader ivec2" },
|
||||
{ vshader: "vshader-simple", fshader: "fshader-ivec3", desc: "fragment shader ivec3" },
|
||||
{ vshader: "vshader-simple", fshader: "fshader-ivec4", desc: "fragment shader ivec4" },
|
||||
];
|
||||
|
||||
for (var idx = 0; idx < testCases.length; ++idx) {
|
||||
var test = testCases[idx];
|
||||
|
||||
debug("");
|
||||
var program = wtu.setupProgram(gl, [test.vshader, test.fshader], ["aPosition"]);
|
||||
if (!program) {
|
||||
testFailed("Fail to set up program");
|
||||
} else {
|
||||
debug("Testing " + test.desc);
|
||||
wtu.drawUnitQuad(gl);
|
||||
wtu.checkCanvas(gl, [255, 0, 0, 255]);
|
||||
gl.deleteProgram(program);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from testing");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
test();
|
||||
|
||||
debug("");
|
||||
var successfullyParsed = true;
|
||||
</script>
|
||||
<script src="../../js/js-test-post.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,66 @@
|
||||
<!--
|
||||
Copyright (c) 2021 The Khronos Group Inc.
|
||||
Use of this source code is governed by an MIT-style license that can be
|
||||
found in the LICENSE.txt file.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Shader identified as containing reciprocal square root of sum of squares should not crash</title>
|
||||
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
|
||||
<link rel="stylesheet" href="../../resources/glsl-feature-tests.css"/>
|
||||
<script src="../../js/js-test-pre.js"></script>
|
||||
<script src="../../js/webgl-test-utils.js"></script>
|
||||
<script src="../../js/glsl-conformance-test.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<script id="vshader" type="x-shader/x-vertex">#version 300 es
|
||||
void main() {
|
||||
gl_Position = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
</script>
|
||||
<script id="fshader" type="x-shader/x-fragment">#version 300 es
|
||||
precision highp float;
|
||||
|
||||
#define CRASH 1
|
||||
|
||||
out vec4 fragmentColor;
|
||||
void main()
|
||||
{
|
||||
vec2 p = gl_FragCoord.xy;
|
||||
// This expression meets the requirement of being the reciprocal
|
||||
// square root of a sum of squares.
|
||||
float d = 1.0 / length(p);
|
||||
#if CRASH
|
||||
if (p.x > 0.0)
|
||||
{
|
||||
d *= 2.0;
|
||||
}
|
||||
#endif
|
||||
fragmentColor = vec4(d);
|
||||
}
|
||||
</script>
|
||||
<script type="application/javascript">
|
||||
"use strict";
|
||||
description();
|
||||
debug('Regression test for <a href="https://crbug.com/1079309">crbug.com/1079309</a>');
|
||||
const wtu = WebGLTestUtils;
|
||||
const tests = [
|
||||
{
|
||||
vShaderSource: wtu.getScript('vshader'),
|
||||
fShaderSource: wtu.getScript('fshader'),
|
||||
vShaderSuccess: true,
|
||||
fShaderSuccess: true,
|
||||
linkSuccess: true,
|
||||
passMsg: 'Shader containing expression that driver recognizes as reciprocal square root of sum of squares should compile and link'
|
||||
}
|
||||
];
|
||||
|
||||
GLSLConformanceTester.runTests(tests, 2);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -36,6 +36,59 @@ void main()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script id="fshaderDeclarationInsideSwitchDefault" type="x-shader/x-fragment">#version 300 es
|
||||
|
||||
precision highp float;
|
||||
out vec4 my_FragColor;
|
||||
|
||||
uniform int u_zero;
|
||||
|
||||
void main()
|
||||
{
|
||||
my_FragColor = vec4(1, 0, 0, 1);
|
||||
switch (u_zero)
|
||||
{
|
||||
default:
|
||||
ivec2 i;
|
||||
i = ivec2(1, 0);
|
||||
my_FragColor = vec4(0, i[0], 0, 1);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script id="fshaderDeclarationInsideSwitchLiteral" type="x-shader/x-fragment">#version 300 es
|
||||
|
||||
precision highp float;
|
||||
out vec4 my_FragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
my_FragColor = vec4(1, 0, 0, 1);
|
||||
switch (0)
|
||||
{
|
||||
case 0:
|
||||
ivec2 i;
|
||||
i = ivec2(1, 0);
|
||||
my_FragColor = vec4(0, i[0], 0, 1);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script id="fshaderDeclarationInsideSwitchLiteralDefault" type="x-shader/x-fragment">#version 300 es
|
||||
|
||||
precision highp float;
|
||||
out vec4 my_FragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
my_FragColor = vec4(1, 0, 0, 1);
|
||||
switch (0)
|
||||
{
|
||||
default:
|
||||
ivec2 i;
|
||||
i = ivec2(1, 0);
|
||||
my_FragColor = vec4(0, i[0], 0, 1);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script id="fshaderDeclarationInsideSwitchScope" type="x-shader/x-fragment">#version 300 es
|
||||
|
||||
precision highp float;
|
||||
@ -221,6 +274,27 @@ GLSLConformanceTester.runTests([
|
||||
passMsg: 'Declaration inside switch should work.',
|
||||
render: true
|
||||
},
|
||||
{
|
||||
fShaderId: 'fshaderDeclarationInsideSwitchDefault',
|
||||
fShaderSuccess: true,
|
||||
linkSuccess: true,
|
||||
passMsg: 'Declaration inside switch default case should work.',
|
||||
render: true
|
||||
},
|
||||
{
|
||||
fShaderId: 'fshaderDeclarationInsideSwitchLiteral',
|
||||
fShaderSuccess: true,
|
||||
linkSuccess: true,
|
||||
passMsg: 'Declaration inside switch with literal value should work.',
|
||||
render: true
|
||||
},
|
||||
{
|
||||
fShaderId: 'fshaderDeclarationInsideSwitchLiteralDefault',
|
||||
fShaderSuccess: true,
|
||||
linkSuccess: true,
|
||||
passMsg: 'Declaration inside switch with literal value and default case should work.',
|
||||
render: true
|
||||
},
|
||||
{
|
||||
fShaderId: 'fshaderDeclarationInsideSwitchScope',
|
||||
fShaderSuccess: true,
|
||||
|
@ -0,0 +1,106 @@
|
||||
<!--
|
||||
Copyright (c) 2020 The Khronos Group Inc.
|
||||
Use of this source code is governed by an MIT-style license that can be
|
||||
found in the LICENSE.txt file.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Verify (uint(int) >> 31) works correctly (Adreno driver bug)</title>
|
||||
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
|
||||
<script src="../../js/js-test-pre.js"></script>
|
||||
<script src="../../js/webgl-test-utils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="canvas" width="2" height="2"> </canvas>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<script id="vshader-uint-1" type="x-shader/x-vertex">#version 300 es
|
||||
in vec3 aPosition;
|
||||
flat out highp uint uvalue;
|
||||
uniform highp int ivalue;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(aPosition, 1);
|
||||
uvalue = uint(ivalue) >> 31u;
|
||||
}
|
||||
</script>
|
||||
<script id="fshader-uint-1" type="x-shader/x-fragment">#version 300 es
|
||||
flat in highp uint uvalue;
|
||||
out highp vec4 myFragColor;
|
||||
|
||||
void main() {
|
||||
if (uvalue == 1u)
|
||||
myFragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
else
|
||||
myFragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="vshader-simple" type="x-shader/x-vertex">#version 300 es
|
||||
in vec3 aPosition;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(aPosition, 1);
|
||||
}
|
||||
</script>
|
||||
<script id="fshader-uint-2" type="x-shader/x-fragment">#version 300 es
|
||||
uniform highp int ivalue;
|
||||
out highp vec4 myFragColor;
|
||||
|
||||
void main() {
|
||||
uint uvalue = uint(ivalue) >> 31u;
|
||||
|
||||
if (uvalue == 1u)
|
||||
myFragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
else
|
||||
myFragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script type="application/javascript">
|
||||
"use strict";
|
||||
description("Verify (uint(int) >> 31) works correctly");
|
||||
debug("");
|
||||
var wtu = WebGLTestUtils;
|
||||
function test() {
|
||||
var gl = wtu.create3DContext("canvas", undefined, 2);
|
||||
if (!gl) {
|
||||
testFailed("context does not exist");
|
||||
return;
|
||||
}
|
||||
wtu.setupUnitQuad(gl);
|
||||
|
||||
var testCases = [
|
||||
{ vshader: "vshader-uint-1", fshader: "fshader-uint-1", desc: "vertex shader uint" },
|
||||
{ vshader: "vshader-simple", fshader: "fshader-uint-2", desc: "fragment shader uint" },
|
||||
];
|
||||
|
||||
for (var idx = 0; idx < testCases.length; ++idx) {
|
||||
var test = testCases[idx];
|
||||
|
||||
debug("");
|
||||
var program = wtu.setupProgram(gl, [test.vshader, test.fshader], ["aPosition"]);
|
||||
if (!program) {
|
||||
testFailed("Fail to set up program");
|
||||
} else {
|
||||
var uniformLoc = gl.getUniformLocation(program, 'ivalue');
|
||||
gl.uniform1i(uniformLoc, -1);
|
||||
wtu.drawUnitQuad(gl);
|
||||
wtu.checkCanvas(gl, [255, 0, 0, 255]);
|
||||
gl.deleteProgram(program);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from testing");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
test();
|
||||
|
||||
debug("");
|
||||
var successfullyParsed = true;
|
||||
</script>
|
||||
<script src="../../js/js-test-post.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -1,6 +1,7 @@
|
||||
expando-loss-2.html
|
||||
getextension-while-pbo-bound-stability.html
|
||||
instanceof-test.html
|
||||
--min-version 2.0.1 null-object-behaviour-2.html
|
||||
object-deletion-behaviour-2.html
|
||||
uninitialized-test-2.html
|
||||
views-with-offsets.html
|
||||
|
@ -0,0 +1,61 @@
|
||||
<!--
|
||||
Copyright (c) 2019 The Khronos Group Inc.
|
||||
Use of this source code is governed by an MIT-style license that can be
|
||||
found in the LICENSE.txt file.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
|
||||
<script src="../../js/js-test-pre.js"></script>
|
||||
<script src="../../js/webgl-test-utils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
var wtu = WebGLTestUtils;
|
||||
description("Tests calling WebGL 2 APIs without providing the necessary objects");
|
||||
|
||||
var gl = wtu.create3DContext(undefined, undefined, 2);
|
||||
var shouldGenerateGLError = wtu.shouldGenerateGLError;
|
||||
|
||||
|
||||
for (let nullOrUndefined of [null, undefined]) {
|
||||
shouldGenerateGLError(gl, gl.NO_ERROR, `gl.deleteQuery(${nullOrUndefined})`);
|
||||
shouldGenerateGLError(gl, gl.NO_ERROR, `gl.isQuery(${nullOrUndefined})`);
|
||||
shouldGenerateGLError(gl, gl.NO_ERROR, `gl.deleteSync(${nullOrUndefined})`);
|
||||
shouldGenerateGLError(gl, gl.NO_ERROR, `gl.isSync(${nullOrUndefined})`);
|
||||
shouldGenerateGLError(gl, gl.NO_ERROR, `gl.deleteTransformFeedback(${nullOrUndefined})`);
|
||||
shouldGenerateGLError(gl, gl.NO_ERROR, `gl.isTransformFeedback(${nullOrUndefined})`);
|
||||
shouldGenerateGLError(gl, gl.NO_ERROR, `gl.deleteSampler(${nullOrUndefined})`);
|
||||
shouldGenerateGLError(gl, gl.NO_ERROR, `gl.isSampler(${nullOrUndefined})`);
|
||||
shouldGenerateGLError(gl, gl.NO_ERROR, `gl.deleteVertexArray(${nullOrUndefined})`);
|
||||
shouldGenerateGLError(gl, gl.NO_ERROR, `gl.isVertexArray(${nullOrUndefined})`);
|
||||
|
||||
shouldGenerateGLError(gl, gl.NO_ERROR, `gl.bindSampler(0, ${nullOrUndefined})`);
|
||||
shouldThrow(`gl.samplerParameteri(${nullOrUndefined}, gl.TEXTURE_MAG_FILTER, gl.NEAREST)`);
|
||||
shouldThrow(`gl.samplerParameterf(${nullOrUndefined}, gl.TEXTURE_MAX_LOD, 1)`);
|
||||
shouldThrow(`gl.getSamplerParameter(${nullOrUndefined}, gl.TEXTURE_MAX_LOD)`);
|
||||
|
||||
shouldThrow(`gl.waitSync(${nullOrUndefined}, 0, 0)`);
|
||||
shouldThrow(`gl.clientWaitSync(${nullOrUndefined}, 0, 0)`);
|
||||
shouldThrow(`gl.getSyncParameter(${nullOrUndefined}, gl.OBJECT_TYPE)`);
|
||||
|
||||
shouldGenerateGLError(gl, gl.NO_ERROR, `gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, ${nullOrUndefined})`);
|
||||
shouldThrow(`gl.transformFeedbackVaryings(${nullOrUndefined}, [], gl.SEPARATE_ATTRIBS)`);
|
||||
|
||||
shouldGenerateGLError(gl, gl.NO_ERROR, `gl.bindVertexArray(${nullOrUndefined})`);
|
||||
}
|
||||
|
||||
|
||||
var successfullyParsed = true;
|
||||
</script>
|
||||
|
||||
<script src="../../js/js-test-post.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -122,6 +122,16 @@ function runCurrentQueryTest() {
|
||||
gl.beginQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, q1);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "beginning a deleted query object");
|
||||
shouldBeNull("gl.getQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, gl.CURRENT_QUERY)");
|
||||
|
||||
debug("");
|
||||
debug("Firefox bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1636525");
|
||||
|
||||
q1 = gl.createQuery();
|
||||
gl.deleteQuery(q1);
|
||||
wtu.glErrorShouldBe(gl, 0, "DeleteQuery after CreateQuery");
|
||||
gl.beginQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, q1);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Begining a deleted query");
|
||||
shouldBeNull("gl.getQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, gl.CURRENT_QUERY)");
|
||||
}
|
||||
|
||||
function runObjectTest() {
|
||||
|
@ -322,6 +322,7 @@ function testPackParameters(usePixelPackBuffer)
|
||||
runTestIteration(0, 0, 2, 3, {alignment:8, skipPixels:2}, usePixelPackBuffer, false);
|
||||
runTestIteration(0, 0, 2, 3, {alignment:8, skipPixels:1, skipRows:3}, usePixelPackBuffer, false);
|
||||
runTestIteration(0, 0, 2, 3, {alignment:8, skipRows:3}, usePixelPackBuffer, true);
|
||||
runTestIteration(0, 0, 2, 3, {skipPixels:1, rowLength:4}, usePixelPackBuffer, true);
|
||||
}
|
||||
|
||||
debug("");
|
||||
|
@ -412,6 +412,29 @@ testFramebufferWithImagesOfDifferentSizes();
|
||||
testUsingIncompleteFramebuffer();
|
||||
testReadingFromMissingAttachment();
|
||||
|
||||
// -
|
||||
|
||||
debug("");
|
||||
debug("Test calling framebufferTexture2D with impossible mip levels.");
|
||||
|
||||
const fb = gl.createFramebuffer();
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
|
||||
|
||||
const tex = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex);
|
||||
|
||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 1000);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Mip level attachment impossibly high.");
|
||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 10);
|
||||
wtu.glErrorShouldBe(gl, 0, "Mip level attachment within acceptable range.");
|
||||
|
||||
// Firefox bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1636517 :
|
||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 1000);
|
||||
wtu.glErrorShouldBe(gl, 0, "Mip level detachment can be impossibly high.");
|
||||
shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)", "0");
|
||||
|
||||
// -
|
||||
|
||||
debug("")
|
||||
var successfullyParsed = true;
|
||||
</script>
|
||||
|
@ -78,8 +78,8 @@ var testReadBufferOnFBO = function() {
|
||||
|
||||
var maxColorAttachments = gl.getParameter(gl.MAX_COLOR_ATTACHMENTS);
|
||||
gl.readBuffer(gl.COLOR_ATTACHMENT0 + maxColorAttachments);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM,
|
||||
"calling readBuffer with GL_COLOR_ATTACHMENTi that exceeds MAX_COLOR_ATTACHMENT on fbo should generate INVALID_ENUM.");
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
|
||||
"calling readBuffer with GL_COLOR_ATTACHMENTi that exceeds MAX_COLOR_ATTACHMENT on fbo should generate INVALID_OPERATION.");
|
||||
gl.readBuffer(gl.COLOR_ATTACHMENT1);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR,
|
||||
"calling readBuffer with GL_COLOR_ATTACHMENT1 on the fbo should succeed.");
|
||||
|
@ -20,10 +20,12 @@ clear-func-buffer-type-match.html
|
||||
draw-buffers.html
|
||||
--min-version 2.0.1 draw-buffers-dirty-state-bug.html
|
||||
--min-version 2.0.1 draw-buffers-driver-hang.html
|
||||
--min-version 2.0.1 draw-buffers-sparse-output-locations.html
|
||||
--min-version 2.0.1 draw-with-integer-texture-base-level.html
|
||||
element-index-uint.html
|
||||
--min-version 2.0.1 framebuffer-completeness-draw-framebuffer.html
|
||||
framebuffer-completeness-unaffected.html
|
||||
--min-version 2.0.1 framebuffer-mismatched-attachment-targets.html
|
||||
--min-version 2.0.1 framebuffer-render-to-layer.html
|
||||
--min-version 2.0.1 framebuffer-render-to-layer-angle-issue.html
|
||||
--min-version 2.0.1 framebuffer-texture-changing-base-level.html
|
||||
@ -36,6 +38,7 @@ instanced-arrays.html
|
||||
--min-version 2.0.1 line-rendering-quality.html
|
||||
--min-version 2.0.1 multisampling-fragment-evaluation.html
|
||||
out-of-bounds-index-buffers-after-copying.html
|
||||
--min-version 2.0.1 rasterizer-discard-and-implicit-clear.html
|
||||
--min-version 2.0.1 read-draw-when-missing-image.html
|
||||
rgb-format-support.html
|
||||
uniform-block-buffer-size.html
|
||||
|
@ -72,57 +72,51 @@ function blitframebuffer_filter_outofbounds(readbufferFormat, drawbufferFormat,
|
||||
|
||||
if (gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
|
||||
// Blit read framebuffer to the image in draw framebuffer.
|
||||
var test = [
|
||||
var tests = [
|
||||
// [srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1]
|
||||
[-2, -2, 4, 4, 1, 1, 4, 4], // only src region is out-of-bounds, dst region has different width/height as src region.
|
||||
[-2, -2, 4, 4, 1, 1, 7, 7], // only src region is out-of-bounds, dst region has the same width/height as src region.
|
||||
[0, 0, 6, 6, 7, 7, 10, 10], // only dst region is out-of-bounds, dst region has different width/height as src region after dst region is clipped to the bounds of draw buffer.
|
||||
[0, 0, 6, 6, 4, 4, 10, 10], // only dst region is out-of-bounds, dst region has the same width/height as src region after dst region is clipped to the bounds of draw buffer.
|
||||
[-2, -2, 4, 4, 7, 7, 10, 10], // both src and dst region are out-of-bounds, dst region has different width/height as src region after dst region is clipped to the bounds of draw buffer.
|
||||
[-2, -2, 4, 4, 4, 4, 10, 10], // both src and dst region are out-of-bounds, dst region has the same width/height as src region after dst region is clipped to the bounds of draw buffer.
|
||||
[-2, -2, 4, 4, 2, 2, 10, 10], // both src and dst region are out-of-bounds. There are some dst pixels (x and y are within [4, 8] , and x or y equals to 4) whose corresponding src pixels are partially inside and partially outside the real sampling area of the src region (the real sampling area is [0, 0, 4, 4]). But the centers of such src pixels are lying outside the real sampling area.
|
||||
[-2, -2, 4, 4, 3, 3, 10, 10], // both src and dst region are out-of-bounds. There are some dst pixels (x and y are within [4, 7] , and x or y equals to 5) whose corresponding src pixels are partially inside and partially outside the real sampling area of the src region (the real sampling area is [0, 0, 4, 4]). But the centers of such src pixels are lying inside the real sampling area.
|
||||
[-2, -2, 4, 4, 10, 10, 2, 2], // both src and dst region are out-of-bounds, and the dst coordinates are reversed. There are some dst pixels (x and y are within [2, 7] , and x or y equals to 7) whose corresponding src pixels are partially inside and partially outside the real sampling area of the src region (the real sampling area is [0, 0, 4, 4]). But the centers of such src pixels are lying outside the real sampling area.
|
||||
[-2, -2, 4, 4, 10, 10, 3, 3], // both src and dst region are out-of-bounds, and the dst coordinates are reversed. There are some dst pixels (x and y are within [3, 7] , and x or y equals to 7) whose corresponding src pixels are partially inside and partially outside the read sampling area of the src region (the real sampling area is [0, 0, 4, 4]). But the centers of such src pixels are lying inside the real sampling area.
|
||||
|
||||
{ args: [-2, -2, 4, 4, 1, 1, 4, 4], changedDstRect: [2, 2, 4, 4], desc: 'only src region is out-of-bounds, dst region has different width/height as src region.'},
|
||||
{ args: [-2, -2, 4, 4, 1, 1, 7, 7], changedDstRect: [3, 3, 7, 7], desc: 'only src region is out-of-bounds, dst region has the same width/height as src region.'},
|
||||
{ args: [0, 0, 6, 6, 7, 7, 10, 10], changedDstRect: [7, 7, 8, 8], desc: 'only dst region is out-of-bounds, dst region has different width/height as src region after dst region is clipped to the bounds of draw buffer.'},
|
||||
{ args: [0, 0, 6, 6, 4, 4, 10, 10], changedDstRect: [4, 4, 8, 8], desc: 'only dst region is out-of-bounds, dst region has the same width/height as src region after dst region is clipped to the bounds of draw buffer.'},
|
||||
{ args: [-2, -2, 4, 4, 7, 7, 10, 10], changedDstRect: [8, 8, 8, 8], desc: 'both src and dst region are out-of-bounds, dst region has different width/height as src region after dst region is clipped to the bounds of draw buffer.'},
|
||||
{ args: [-2, -2, 4, 4, 4, 4, 10, 10], changedDstRect: [6, 6, 8, 8], desc: 'both src and dst region are out-of-bounds, dst region has the same width/height as src region after dst region is clipped to the bounds of draw buffer.'},
|
||||
{ args: [-2, -2, 4, 4, 2, 2, 10, 10], changedDstRect: [2 + 2/6*8, 2 + 2/6*8, 8, 8], desc: 'both src and dst region are out-of-bounds. There are some dst pixels (x and y are within [4, 8] , and x or y equals to 4) whose corresponding src pixels are partially inside and partially outside the real sampling area of the src region (the real sampling area is [0, 0, 4, 4]). But the centers of such src pixels are lying outside the real sampling area.'},
|
||||
{ args: [-2, -2, 4, 4, 3, 3, 10, 10], changedDstRect: [5, 5, 8, 8], desc: 'both src and dst region are out-of-bounds. There are some dst pixels (x and y are within [4, 7] , and x or y equals to 5) whose corresponding src pixels are partially inside and partially outside the real sampling area of the src region (the real sampling area is [0, 0, 4, 4]). But the centers of such src pixels are lying inside the real sampling area.'},
|
||||
{ args: [-2, -2, 4, 4, 10, 10, 2, 2], changedDstRect: [2, 2, 7, 7], desc: 'both src and dst region are out-of-bounds, and the dst coordinates are reversed. There are some dst pixels (x and y are within [2, 7] , and x or y equals to 7) whose corresponding src pixels are partially inside and partially outside the real sampling area of the src region (the real sampling area is [0, 0, 4, 4]). But the centers of such src pixels are lying outside the real sampling area.'},
|
||||
{ args: [-2, -2, 4, 4, 10, 10, 3, 3], changedDstRect: [3, 3, 8, 8], desc: 'both src and dst region are out-of-bounds, and the dst coordinates are reversed. There are some dst pixels (x and y are within [3, 7] , and x or y equals to 7) whose corresponding src pixels are partially inside and partially outside the read sampling area of the src region (the real sampling area is [0, 0, 4, 4]). But the centers of such src pixels are lying inside the real sampling area.'},
|
||||
];
|
||||
|
||||
var realBlittedDstRegion = [
|
||||
[2, 2, 4, 4],
|
||||
[3, 3, 7, 7],
|
||||
[7, 7, 8, 8],
|
||||
[4, 4, 8, 8],
|
||||
[8, 8, 8, 8],
|
||||
[6, 6, 8, 8],
|
||||
[5, 5, 8, 8],
|
||||
[5, 5, 8, 8],
|
||||
[2, 2, 7, 7],
|
||||
[3, 3, 8, 8],
|
||||
]
|
||||
var readbufferHasSRGBImage = (readbufferFormat == gl.SRGB8_ALPHA8);
|
||||
var drawbufferHasSRGBImage = (drawbufferFormat == gl.SRGB8_ALPHA8);
|
||||
|
||||
for (var i = 0; i < test.length; ++i) {
|
||||
for (const test of tests) {
|
||||
const args = test.args;
|
||||
const changedDstRect = test.changedDstRect;
|
||||
debug("");
|
||||
debug("both the read framebuffer and draw framebuffer bounds are [0, 0, 8, 8]");
|
||||
debug("blitting from src region [" + test[i][0] + ", " + test[i][1] + ", " + test[i][2] + ", " + test[i][3] + "] to dst region [" + test[i][4] + ", " + test[i][5] + ", " + test[i][6] + ", " + test[i][7] + "]");
|
||||
debug("Both the read framebuffer and draw framebuffer bounds are [0, 0, 8, 8]");
|
||||
debug(`Blitting from src region [${args.slice(0, 4)}] to dst region [${args.slice(4, 8)}]`);
|
||||
debug(`Expects changed dst region of [${changedDstRect}]`);
|
||||
debug(`Explaination: ${test.desc}`);
|
||||
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_read);
|
||||
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw);
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex_draw);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, drawbufferFormat, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
||||
gl.blitFramebuffer(test[i][0], test[i][1], test[i][2], test[i][3], test[i][4], test[i][5], test[i][6], test[i][7], gl.COLOR_BUFFER_BIT, filter);
|
||||
gl.blitFramebuffer(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], gl.COLOR_BUFFER_BIT, filter);
|
||||
|
||||
// Read pixels and check the correctness.
|
||||
var pixels = new Uint8Array(size * size * 4);
|
||||
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_draw);
|
||||
gl.readPixels(0, 0, size, size, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
|
||||
|
||||
|
||||
for (var ii = 0; ii < size; ++ii) {
|
||||
for (var jj = 0; jj < size; ++jj) {
|
||||
var loc = ii * size + jj;
|
||||
var color = [pixels[loc * 4], pixels[loc * 4 + 1], pixels[loc * 4 + 2], pixels[loc * 4 + 3]];
|
||||
|
||||
var expectedColor = [0, 0, 0, 0];
|
||||
if (ii >= realBlittedDstRegion[i][0] && ii < realBlittedDstRegion[i][2] && jj >= realBlittedDstRegion[i][1] && jj < realBlittedDstRegion[i][3]) {
|
||||
if (ii >= changedDstRect[0] && ii < changedDstRect[2] && jj >= changedDstRect[1] && jj < changedDstRect[3]) {
|
||||
expectedColor = [0x20, 0x20, 0x20, 0xff];
|
||||
|
||||
// We may need to covert the color space for pixels in blit region
|
||||
@ -163,6 +157,7 @@ if (!gl) {
|
||||
var filters = [gl.LINEAR, gl.NEAREST];
|
||||
for (var ii = 0; ii < filters.length; ++ii) {
|
||||
blitframebuffer_filter_outofbounds(gl.RGBA8, gl.RGBA8, filters[ii]);
|
||||
break;
|
||||
blitframebuffer_filter_outofbounds(gl.RGBA8, gl.SRGB8_ALPHA8, filters[ii]);
|
||||
blitframebuffer_filter_outofbounds(gl.SRGB8_ALPHA8, gl.RGBA8, filters[ii]);
|
||||
blitframebuffer_filter_outofbounds(gl.SRGB8_ALPHA8, gl.SRGB8_ALPHA8, filters[ii]);
|
||||
|
@ -71,7 +71,7 @@ function clear_srgb_color_buffer(iter) {
|
||||
}
|
||||
|
||||
var color_ref = wtu.linearToSRGB(color);
|
||||
var tolerance = 1;
|
||||
var tolerance = 3;
|
||||
var msg = "";
|
||||
wtu.checkCanvasRect(gl, 0, 0, size, size, color_ref, msg, tolerance);
|
||||
}
|
||||
|
@ -0,0 +1,108 @@
|
||||
<!--
|
||||
Copyright (c) 2019 The Khronos Group Inc.
|
||||
Use of this source code is governed by an MIT-style license that can be
|
||||
found in the LICENSE.txt file.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>WebGL Conformance Tests: Verify drawBuffers sparse output locations</title>
|
||||
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
|
||||
<script src="../../js/js-test-pre.js"></script>
|
||||
<script src="../../js/webgl-test-utils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
<canvas id="canvas" width="1" height="1" style="width: 4px; height: 4px;"> </canvas>
|
||||
<div id="console"></div>
|
||||
|
||||
<script id="vs" type="x-shader/x-vertex">#version 300 es
|
||||
void main() {
|
||||
gl_PointSize = 100.0;
|
||||
gl_Position = vec4(0, 0, 0, 1);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="fs" type="x-shader/x-fragment">#version 300 es
|
||||
// fragment shader only outputs to attachments 1 and 3
|
||||
precision highp float;
|
||||
layout(location = 1) out vec4 output1;
|
||||
layout(location = 3) out vec4 output2;
|
||||
void main()
|
||||
{
|
||||
output1 = vec4(0.0, 1.0, 0.0, 1.0);
|
||||
output2 = vec4(0.0, 0.0, 1.0, 1.0);
|
||||
}
|
||||
|
||||
</script>
|
||||
<script>
|
||||
"use strict";
|
||||
description("This test verifies sparse output locations of fragment shaders render correctly");
|
||||
|
||||
debug("");
|
||||
|
||||
var wtu = WebGLTestUtils;
|
||||
var canvas = document.getElementById("canvas");
|
||||
var gl = wtu.create3DContext(canvas, null, 2);
|
||||
|
||||
if (!gl) {
|
||||
testFailed("WebGL context does not exist");
|
||||
} else {
|
||||
testPassed("WebGL context exists");
|
||||
runTests();
|
||||
}
|
||||
|
||||
function testAttachment(attachment, expected) {
|
||||
gl.readBuffer(gl.COLOR_ATTACHMENT0 + attachment);
|
||||
wtu.checkCanvas(gl, expected, `check COLOR_ATTACHMENT${attachment}`, 1);
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
var program = wtu.setupProgram(gl, ["vs", "fs"]);
|
||||
if (!program) {
|
||||
testFailed("Set up program failed");
|
||||
return;
|
||||
}
|
||||
gl.useProgram(program);
|
||||
|
||||
// create a framebuffer with 4 1x1 pixel color attachments
|
||||
const fb = gl.createFramebuffer();
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
|
||||
|
||||
for (let i = 0; i < 4; ++i) {
|
||||
const tex = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, gl.TEXTURE_2D, tex, 0);
|
||||
}
|
||||
|
||||
// draw only to the 1st and 3rd attachments
|
||||
gl.drawBuffers([
|
||||
gl.NONE,
|
||||
gl.COLOR_ATTACHMENT1,
|
||||
gl.NONE,
|
||||
gl.COLOR_ATTACHMENT3,
|
||||
]);
|
||||
|
||||
// draw
|
||||
gl.drawArrays(gl.POINTS, 0, 1);
|
||||
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No GL error from set up");
|
||||
|
||||
// check we got the correct values
|
||||
testAttachment(0, [0, 0, 0, 0]);
|
||||
testAttachment(1, [0, 255, 0, 255]);
|
||||
testAttachment(2, [0, 0, 0, 0]);
|
||||
testAttachment(3, [0, 0, 255, 255]);
|
||||
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No GL error from testing");
|
||||
}
|
||||
|
||||
var successfullyParsed = true;
|
||||
</script>
|
||||
<script src="../../js/js-test-post.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,162 @@
|
||||
<!--
|
||||
Copyright (c) 2020 The Khronos Group Inc.
|
||||
Use of this source code is governed by an MIT-style license that can be
|
||||
found in the LICENSE.txt file.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>WebGL2 can render to framebuffer attachments with different targets</title>
|
||||
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
|
||||
<script src="../../js/js-test-pre.js"></script>
|
||||
<script src="../../js/webgl-test-utils.js"></script>
|
||||
<script id="vshader" type="x-shader/x-vertex">#version 300 es
|
||||
void main(void) {
|
||||
gl_Position = vec4(-0.5, -0.5, 0, 1);
|
||||
gl_PointSize = 1.0;
|
||||
}
|
||||
</script>
|
||||
<script id="fshader" type="x-shader/x-fragment">#version 300 es
|
||||
precision mediump float;
|
||||
out vec4 outColor;
|
||||
void main() {
|
||||
outColor = vec4(0, 1, 0, 1);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="example" width="1", height="1"></canvas>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<script>
|
||||
"use strict";
|
||||
debug("");
|
||||
|
||||
description("Test framebuffer attachments with different targets");
|
||||
|
||||
const wtu = WebGLTestUtils;
|
||||
const gl = wtu.create3DContext("example", undefined, 2);
|
||||
|
||||
if (!gl) {
|
||||
testFailed("WebGL context creation failed");
|
||||
} else {
|
||||
testPassed("WebGL context creation succeeded");
|
||||
runTest();
|
||||
}
|
||||
|
||||
function newResource(target, mipLevels, format, size) {
|
||||
let ret;
|
||||
switch (target) {
|
||||
case gl.RENDERBUFFER: {
|
||||
ret = gl.createRenderbuffer();
|
||||
ret.mips = [ ret ];
|
||||
for (let i = 1; i < mipLevels; i++) {
|
||||
ret.mips.push(gl.createRenderbuffer());
|
||||
}
|
||||
for (const i in ret.mips) {
|
||||
const rb = ret.mips[i];
|
||||
gl.bindRenderbuffer(target, rb);
|
||||
gl.renderbufferStorage(target, format, size>>i, size>>i);
|
||||
}
|
||||
ret.attach = (attachEnum, mipLevel) => {
|
||||
const rb = ret.mips[mipLevel];
|
||||
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachEnum, gl.RENDERBUFFER, rb);
|
||||
};
|
||||
break;
|
||||
}
|
||||
case gl.TEXTURE_2D:
|
||||
case gl.TEXTURE_CUBE_MAP: {
|
||||
ret = gl.createTexture();
|
||||
gl.bindTexture(target, ret);
|
||||
gl.texStorage2D(target, mipLevels, format, size, size);
|
||||
let imageTarget = target;
|
||||
if (imageTarget == gl.TEXTURE_CUBE_MAP) {
|
||||
imageTarget = gl.TEXTURE_CUBE_MAP_POSITIVE_X+2; // Deliberately don't choose the first image.
|
||||
}
|
||||
ret.attach = (attachEnum, mipLevel) => {
|
||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, attachEnum, imageTarget, ret, mipLevel);
|
||||
};
|
||||
break;
|
||||
}
|
||||
case gl.TEXTURE_3D:
|
||||
case gl.TEXTURE_2D_ARRAY: {
|
||||
ret = gl.createTexture();
|
||||
gl.bindTexture(target, ret);
|
||||
gl.texStorage3D(target, mipLevels, format, size, size, 1);
|
||||
ret.attach = (attachEnum, mipLevel) => {
|
||||
gl.framebufferTextureLayer(gl.FRAMEBUFFER, attachEnum, ret, mipLevel, 0);
|
||||
};
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new Error();
|
||||
}
|
||||
ret.target = wtu.glEnumToString(gl, target);
|
||||
ret.format = wtu.glEnumToString(gl, format);
|
||||
return ret;
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
const MIP_LEVELS = 2;
|
||||
const SIZE = 2;
|
||||
|
||||
gl.clearColor(1, 0, 0, 1);
|
||||
|
||||
const program = wtu.setupProgram(gl, ['vshader','fshader'], [], console.log.bind(console));
|
||||
gl.useProgram(program);
|
||||
|
||||
const colorResList = [
|
||||
newResource(gl.RENDERBUFFER, MIP_LEVELS, gl.RGBA8, SIZE),
|
||||
newResource(gl.TEXTURE_2D, MIP_LEVELS, gl.RGBA8, SIZE),
|
||||
newResource(gl.TEXTURE_CUBE_MAP, MIP_LEVELS, gl.RGBA8, SIZE),
|
||||
newResource(gl.TEXTURE_3D, MIP_LEVELS, gl.RGBA8, SIZE),
|
||||
newResource(gl.TEXTURE_2D_ARRAY, MIP_LEVELS, gl.RGBA8, SIZE),
|
||||
];
|
||||
|
||||
const depthResList = [
|
||||
newResource(gl.RENDERBUFFER, MIP_LEVELS, gl.DEPTH_COMPONENT16, SIZE),
|
||||
newResource(gl.TEXTURE_2D, MIP_LEVELS, gl.DEPTH_COMPONENT16, SIZE),
|
||||
newResource(gl.TEXTURE_CUBE_MAP, MIP_LEVELS, gl.DEPTH_COMPONENT16, SIZE),
|
||||
//newResource(gl.TEXTURE_3D, MIP_LEVELS, gl.DEPTH_COMPONENT16, SIZE), // Depth formats forbidden for TEXTURE_3D.
|
||||
newResource(gl.TEXTURE_2D_ARRAY, MIP_LEVELS, gl.DEPTH_COMPONENT16, SIZE),
|
||||
];
|
||||
|
||||
const fb = gl.createFramebuffer();
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
|
||||
for (const color of colorResList) {
|
||||
for (const depth of depthResList) {
|
||||
debug(`\ncolor: ${color.target}; depth: ${depth.target}`);
|
||||
for (let mipLevel = 0; mipLevel < MIP_LEVELS; mipLevel++) {
|
||||
debug(`mipLevel: ${mipLevel}`);
|
||||
color.attach(gl.COLOR_ATTACHMENT0, mipLevel);
|
||||
depth.attach(gl.DEPTH_ATTACHMENT, mipLevel);
|
||||
const maybeStatus = wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER, [gl.FRAMEBUFFER_COMPLETE, gl.FRAMEBUFFER_UNSUPPORTED]);
|
||||
if (!maybeStatus || maybeStatus[0] != gl.FRAMEBUFFER_COMPLETE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
wtu.checkCanvas(gl, [255, 0, 0, 255], `framebuffer layer ${mipLevel} should be cleared red`);
|
||||
|
||||
gl.drawArrays(gl.POINTS, 0, 1);
|
||||
wtu.checkCanvas(gl, [0, 255, 0, 255], `framebuffer layer ${mipLevel} should be drawn green`);
|
||||
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR, `No errors`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// make sure we were not rendering to the canvas.
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null)
|
||||
wtu.checkCanvas(gl, [0, 0, 0, 0], "canvas should be zero");
|
||||
}
|
||||
|
||||
debug("");
|
||||
var successfullyParsed = true;
|
||||
</script>
|
||||
<script src="../../js/js-test-post.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -123,6 +123,9 @@ function runOutputTests() {
|
||||
0.0, 1.0, 0.0, 1.0, // Green
|
||||
0.0, 0.0, 1.0, 1.0, // Blue
|
||||
1.0, 1.0, 0.0, 1.0, // Yellow
|
||||
// extra data when colorLoc divisor is set back to 0
|
||||
1.0, 1.0, 0.0, 1.0, // Yellow
|
||||
1.0, 1.0, 0.0, 1.0, // Yellow
|
||||
]);
|
||||
var colorBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
|
||||
@ -174,6 +177,45 @@ function runOutputTests() {
|
||||
gl.drawArraysInstanced(desktopGL['POLYGON'], 0, 6, instanceCount);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "drawArraysInstanced with POLYGON should return INVALID_ENUM");
|
||||
|
||||
debug("Testing drawArraysInstanced with param 'first' > 0");
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
wtu.setupQuad(gl, {
|
||||
positionLocation: 0,
|
||||
scale: 0.5
|
||||
});
|
||||
var offsetsHalf = new Float32Array([
|
||||
-0.5, 0.5,
|
||||
0.5, 0.5,
|
||||
-0.5, -0.5,
|
||||
0.5, -0.5
|
||||
]);
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, offsetBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, offsetsHalf, gl.STATIC_DRAW);
|
||||
|
||||
gl.drawArraysInstanced(gl.TRIANGLES, 3, 3, instanceCount);
|
||||
var w = Math.floor(0.25*canvas.width),
|
||||
h = Math.floor(0.25*canvas.height);
|
||||
wtu.checkCanvasRect(gl, Math.ceil(0.25*canvas.width), 0.5*canvas.height, w, h, [255, 0, 0, 255]);
|
||||
wtu.checkCanvasRect(gl, Math.ceil(0.75*canvas.width), 0.5*canvas.height, w, h, [0, 255, 0, 255]);
|
||||
wtu.checkCanvasRect(gl, Math.ceil(0.25*canvas.width), 0, w, h, [0, 0, 255, 255]);
|
||||
wtu.checkCanvasRect(gl, Math.ceil(0.75*canvas.width), 0, w, h, [255, 255, 0, 255]);
|
||||
|
||||
debug("Testing drawArraysInstanced with attributes 'divisor' reset to 0");
|
||||
debug("Correct rendering output: 4 yellow triangles");
|
||||
debug("Possible incorrect rendering output: missing triangles, or triangles with different color at each vertex");
|
||||
gl.vertexAttribDivisor(colorLoc, 0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
gl.drawArraysInstanced(gl.TRIANGLES, 3, 3, instanceCount);
|
||||
wtu.checkCanvasRect(gl, Math.ceil(0.25*canvas.width), 0.5*canvas.height, w, h, [255, 255, 0, 255]);
|
||||
wtu.checkCanvasRect(gl, Math.ceil(0.75*canvas.width), 0.5*canvas.height, w, h, [255, 255, 0, 255]);
|
||||
wtu.checkCanvasRect(gl, Math.ceil(0.25*canvas.width), 0, w, h, [255, 255, 0, 255]);
|
||||
wtu.checkCanvasRect(gl, Math.ceil(0.75*canvas.width), 0, w, h, [255, 255, 0, 255]);
|
||||
gl.vertexAttribDivisor(colorLoc, 1);
|
||||
|
||||
wtu.setupUnitQuad(gl, 0);
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, offsetBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, offsets, gl.STATIC_DRAW);
|
||||
|
||||
// Draw 2: Draw indexed instances
|
||||
debug("Testing drawElementsInstanced");
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
@ -0,0 +1,149 @@
|
||||
<!--
|
||||
Copyright (c) 2020 The Khronos Group Inc.
|
||||
Use of this source code is governed by an MIT-style license that can be
|
||||
found in the LICENSE.txt file.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>RASTERIZER_DISCARD doesn't affect implicit clears</title>
|
||||
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
|
||||
<script src="../../js/js-test-pre.js"></script>
|
||||
<script src="../../js/webgl-test-utils.js"></script>
|
||||
<script id="vshader" type="x-shader/x-vertex">#version 300 es
|
||||
layout(location=0) in vec2 vPosition;
|
||||
uniform float xTranslation;
|
||||
void main(void) {
|
||||
gl_Position = vec4(vPosition[0] + xTranslation, vPosition[1], 0.0, 1.0);
|
||||
}
|
||||
</script>
|
||||
<script id="fshader" type="x-shader/x-fragment">#version 300 es
|
||||
precision mediump float;
|
||||
uniform vec4 color;
|
||||
out vec4 outColor;
|
||||
void main() {
|
||||
outColor = color;
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="example"></canvas>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<script>
|
||||
"use strict";
|
||||
debug("");
|
||||
|
||||
description("Enabling RASTERIZER_DISCARD should not affect implicit clears");
|
||||
|
||||
const wtu = WebGLTestUtils;
|
||||
const canvas = document.getElementById("example");
|
||||
const sz = canvas.width = canvas.height = 256;
|
||||
const gl = wtu.create3DContext(canvas, undefined, 2);
|
||||
const NUM_FRAMES = 15;
|
||||
let framesToGo = NUM_FRAMES;
|
||||
let xTranslationLoc;
|
||||
let colorLoc;
|
||||
const positionLocation = 0;
|
||||
const red = [ 1.0, 0.0, 0.0, 1.0 ];
|
||||
const green = [ 0.0, 1.0, 0.0, 1.0 ];
|
||||
const transparentBlackRender = [ 0, 0, 0, 0 ];
|
||||
const greenRender = [ 0, 255, 0, 255 ];
|
||||
|
||||
if (!gl) {
|
||||
testFailed("WebGL context creation failed");
|
||||
finishTest();
|
||||
} else {
|
||||
testPassed("WebGL context creation succeeded");
|
||||
runDrawTest();
|
||||
}
|
||||
|
||||
function runDrawTest() {
|
||||
debug("Verify that draws with rasterizer discard enabled do not interfere with implicit clears");
|
||||
let prog = wtu.loadProgramFromScript(gl, "vshader", "fshader");
|
||||
gl.useProgram(prog);
|
||||
xTranslationLoc = gl.getUniformLocation(prog, "xTranslation");
|
||||
colorLoc = gl.getUniformLocation(prog, "color");
|
||||
let leftRectBuffer = gl.createBuffer();
|
||||
gl.enableVertexAttribArray(positionLocation);
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, leftRectBuffer);
|
||||
// Create a rectangle covering the left half of the viewport, in
|
||||
// normalized device coordinates.
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
|
||||
0.0, 1.0,
|
||||
-1.0, 1.0,
|
||||
-1.0, -1.0,
|
||||
0.0, 1.0,
|
||||
-1.0, -1.0,
|
||||
0.0, -1.0]), gl.STATIC_DRAW);
|
||||
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
|
||||
requestAnimationFrame(renderDrawTestFrame);
|
||||
}
|
||||
|
||||
function renderDrawTestFrame() {
|
||||
// Animation is required in order to expose this bug. When it
|
||||
// occurs, the rectangle leaves trails behind it.
|
||||
gl.uniform1f(xTranslationLoc, 0.0);
|
||||
gl.enable(gl.RASTERIZER_DISCARD);
|
||||
gl.uniform4fv(colorLoc, red);
|
||||
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
||||
gl.disable(gl.RASTERIZER_DISCARD);
|
||||
|
||||
// Animate the rectangle from the left to the right half of the viewport.
|
||||
gl.uniform1f(xTranslationLoc, (NUM_FRAMES - framesToGo) / NUM_FRAMES);
|
||||
// Draw the last frame with green so any (incorrect) trails are visibly red.
|
||||
if (framesToGo == 0)
|
||||
gl.uniform4fv(colorLoc, green);
|
||||
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
||||
|
||||
if (framesToGo-- == 0) {
|
||||
// The left half of the canvas should be transparent black,
|
||||
// which comes from the implicit clear just before drawing the
|
||||
// rectangle without rasterizer discard enabled.
|
||||
wtu.checkCanvasRect(gl, 0, 0, sz / 2, sz, transparentBlackRender, "left half of canvas should be clear", 3);
|
||||
// The right half of the canvas should be solid green, from
|
||||
// the last render of the translated rectangle.
|
||||
wtu.checkCanvasRect(gl, sz / 2, 0, sz / 2, sz, greenRender, "right half of canvas should be green", 3);
|
||||
runReadPixelsTest();
|
||||
} else {
|
||||
requestAnimationFrame(renderDrawTestFrame);
|
||||
}
|
||||
}
|
||||
|
||||
function runReadPixelsTest() {
|
||||
debug("Verify that readPixels with rasterizer discard enabled receives implicitly cleared data");
|
||||
framesToGo = NUM_FRAMES; // Reset state.
|
||||
// Clear to transparent black.
|
||||
gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
// Start with rasterizer discard enabled.
|
||||
gl.enable(gl.RASTERIZER_DISCARD);
|
||||
requestAnimationFrame(renderReadPixelsTestFrame);
|
||||
}
|
||||
|
||||
function renderReadPixelsTestFrame() {
|
||||
// Rasterizer discard is enabled at the beginning of this test.
|
||||
|
||||
// The canvas should always contain transparent black at the beginning of the frame.
|
||||
wtu.checkCanvasRect(gl, 0, 0, sz, sz, transparentBlackRender, undefined, 3);
|
||||
|
||||
gl.disable(gl.RASTERIZER_DISCARD);
|
||||
// Clear to red.
|
||||
gl.clearColor(1.0, 0.0, 0.0, 1.0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
// Enable rasterizer discard again.
|
||||
gl.enable(gl.RASTERIZER_DISCARD);
|
||||
|
||||
if (--framesToGo == 0) {
|
||||
finishTest();
|
||||
} else {
|
||||
requestAnimationFrame(renderReadPixelsTestFrame);
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -2,6 +2,7 @@
|
||||
--min-version 2.0.1 angle-stuck-depth-textures.html
|
||||
canvas-remains-unchanged-after-used-in-webgl-texture.html
|
||||
--min-version 2.0.1 compressed-tex-from-pbo-crash.html
|
||||
--min-version 2.0.1 compressed-tex-image.html
|
||||
--min-version 2.0.1 copy-texture-cube-map-AMD-bug.html
|
||||
--min-version 2.0.1 copy-texture-cube-map-bug.html
|
||||
copy-texture-image.html
|
||||
@ -10,6 +11,7 @@ copy-texture-image-luma-format.html
|
||||
copy-texture-image-webgl-specific.html
|
||||
--min-version 2.0.1 generate-mipmap-with-large-base-level.html
|
||||
gl-get-tex-parameter.html
|
||||
--min-version 2.0.1 immutable-tex-render-feedback.html
|
||||
--min-version 2.0.1 integer-cubemap-texture-sampling.html
|
||||
--min-version 2.0.1 integer-cubemap-specification-order-bug.html
|
||||
mipmap-fbo.html
|
||||
|
@ -0,0 +1,24 @@
|
||||
<!--
|
||||
Copyright (c) 2020 The Khronos Group Inc.
|
||||
Use of this source code is governed by an MIT-style license that can be
|
||||
found in the LICENSE.txt file.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
|
||||
<script src="../../../js/js-test-pre.js"></script>
|
||||
<script src="../../../js/webgl-test-utils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<script>
|
||||
const contextVersion = 2;
|
||||
</script>
|
||||
<script src="../../../js/tests/compressed-tex-image.js"></script>
|
||||
<script src="../../../js/js-test-post.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,221 @@
|
||||
<!--
|
||||
Copyright (c) 2019 The Khronos Group Inc.
|
||||
Use of this source code is governed by an MIT-style license that can be
|
||||
found in the LICENSE.txt file.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Ensure sampling-feedback detection can allow certain immutable texture uses</title>
|
||||
<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
|
||||
<script src="../../../js/js-test-pre.js"></script>
|
||||
<script src="../../../js/webgl-test-utils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
const wtu = WebGLTestUtils;
|
||||
description();
|
||||
|
||||
const gl = wtu.create3DContext(undefined, undefined, 2);
|
||||
|
||||
function* range(a, b) {
|
||||
a.required;
|
||||
if (b === undefined) {
|
||||
b = a;
|
||||
a = 0;
|
||||
}
|
||||
for (let i = a; i < b; i += 1) {
|
||||
yield i;
|
||||
}
|
||||
}
|
||||
|
||||
const VS = `\
|
||||
void main() {
|
||||
gl_PointSize = 1.0;
|
||||
}
|
||||
`;
|
||||
|
||||
const FS = `\
|
||||
uniform sampler2D u_tex0;
|
||||
void main() {
|
||||
gl_FragColor = texture2D(u_tex0, vec2(0));
|
||||
}
|
||||
`;
|
||||
|
||||
const prog = wtu.loadProgram(gl, VS, FS);
|
||||
gl.useProgram(prog);
|
||||
|
||||
(() => {
|
||||
const MIPS = 3;
|
||||
const SIZE = 10;
|
||||
|
||||
const immutTex = gl.createTexture();
|
||||
immutTex.name = "immutTex";
|
||||
immutTex.immutable = true;
|
||||
gl.bindTexture(gl.TEXTURE_2D, immutTex);
|
||||
gl.texStorage2D(gl.TEXTURE_2D, MIPS, gl.RGBA8, SIZE, SIZE);
|
||||
|
||||
const mutTex = gl.createTexture();
|
||||
mutTex.name = "mutTex";
|
||||
mutTex.immutable = false;
|
||||
gl.bindTexture(gl.TEXTURE_2D, mutTex);
|
||||
for (const mip of range(MIPS)) {
|
||||
const size = SIZE >> mip;
|
||||
gl.texImage2D(gl.TEXTURE_2D, mip, gl.RGBA8, size, size, 0,
|
||||
gl.RGBA, gl.UNSIGNED_BYTE, null);
|
||||
}
|
||||
|
||||
const MAG_FILTERS = [
|
||||
'LINEAR',
|
||||
'NEAREST',
|
||||
];
|
||||
const MIN_FILTERS = [
|
||||
['LINEAR',false],
|
||||
['LINEAR_MIPMAP_LINEAR',true],
|
||||
['LINEAR_MIPMAP_NEAREST',true],
|
||||
['NEAREST',false],
|
||||
['NEAREST_MIPMAP_LINEAR',true],
|
||||
['NEAREST_MIPMAP_NEAREST',true],
|
||||
];
|
||||
|
||||
const fb = gl.createFramebuffer();
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
|
||||
|
||||
debug(`
|
||||
mips: ${MIPS}: [0,${MIPS-1}] (inclusive)
|
||||
size: ${SIZE}`);
|
||||
const texs = [
|
||||
immutTex,
|
||||
mutTex,
|
||||
];
|
||||
for (const tex of texs) {
|
||||
debug(`\
|
||||
|
||||
immutable: ${tex.immutable}`);
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex);
|
||||
|
||||
for (const level_prime_base of range(MIPS+1)) { // `level_base` in GLES
|
||||
// ES 3.0.6 p150
|
||||
let _level_base = level_prime_base;
|
||||
if (tex.immutable) {
|
||||
_level_base = Math.min(_level_base, MIPS-1);
|
||||
}
|
||||
const level_base = _level_base;
|
||||
|
||||
for (let _level_prime_max of range(level_prime_base-1, MIPS+2)) { // `q` in GLES
|
||||
if (_level_prime_max < 0) continue;
|
||||
if (_level_prime_max == MIPS+1) {
|
||||
_level_prime_max = 10000; // This is the default, after all!
|
||||
}
|
||||
const level_prime_max = _level_prime_max;
|
||||
|
||||
// ES 3.0.6 p150
|
||||
let _level_max = level_prime_max;
|
||||
if (tex.immutable) {
|
||||
_level_max = Math.min(Math.max(level_base, level_prime_max), MIPS-1);
|
||||
}
|
||||
const level_max = _level_max;
|
||||
|
||||
const p = Math.floor(Math.log2(SIZE)) + level_base;
|
||||
const q = Math.min(p, level_max);
|
||||
|
||||
debug(`\
|
||||
|
||||
level_prime_base/max: [${level_prime_base}, ${level_prime_max}] (inclusive)
|
||||
level_base/max: [${level_base}, ${level_max}] (inclusive)
|
||||
q: ${q}`);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_BASE_LEVEL,
|
||||
level_prime_base);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAX_LEVEL,
|
||||
level_prime_max);
|
||||
|
||||
const mipComplete = (q <= MIPS-1);
|
||||
|
||||
for (const [minFilter,useMips] of MIN_FILTERS) {
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER,
|
||||
gl[minFilter]);
|
||||
|
||||
// ES3.0 p211
|
||||
const srcMaxSampledMip = (useMips ? q : level_base);
|
||||
|
||||
// ES3.0 p160-161
|
||||
const textureComplete = (srcMaxSampledMip <= MIPS-1) &&
|
||||
(level_base <= level_max);
|
||||
|
||||
for (const magFilter of MAG_FILTERS) {
|
||||
debug(`\
|
||||
|
||||
min: ${minFilter}, mag: ${magFilter}`);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER,
|
||||
gl[magFilter]);
|
||||
|
||||
for (const dstMip of range(0,MIPS+1)) {
|
||||
debug(`
|
||||
mip: ${dstMip}`);
|
||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
|
||||
gl.TEXTURE_2D, tex, dstMip);
|
||||
|
||||
// -
|
||||
|
||||
// ES3.0 p213-214
|
||||
let fbComplete = true;
|
||||
|
||||
// * "The width and height of `image` are non-zero"
|
||||
fbComplete &= (0 <= dstMip && dstMip <= MIPS-1);
|
||||
|
||||
if (!tex.immutable) { // "...does not name an immutable-format texture..."
|
||||
// * "...the value of [level] must be in the range `[level_base, q]`"
|
||||
fbComplete &= (level_base <= dstMip && dstMip <= q);
|
||||
|
||||
// * "...the value of [level] is not `level_base`, then the texture must be mipmap complete"
|
||||
if (dstMip != level_base) {
|
||||
fbComplete &= mipComplete;
|
||||
}
|
||||
}
|
||||
|
||||
// -
|
||||
|
||||
let expectError = 0;
|
||||
let expectStatus = gl.FRAMEBUFFER_COMPLETE;
|
||||
|
||||
// ES3.0 p211
|
||||
let samplingFeedback = (level_base <= dstMip && dstMip <= srcMaxSampledMip);
|
||||
if (!textureComplete) {
|
||||
// Incomplete textures are safe
|
||||
samplingFeedback = false;
|
||||
}
|
||||
if (samplingFeedback) {
|
||||
expectError = gl.INVALID_OPERATION;
|
||||
}
|
||||
if (!fbComplete) {
|
||||
expectStatus = gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
|
||||
expectError = gl.INVALID_FRAMEBUFFER_OPERATION;
|
||||
}
|
||||
|
||||
// -
|
||||
|
||||
wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER,
|
||||
expectStatus, `{immutable: ${tex.immutable}, level_prime_base/max: [${level_prime_base}, ${level_prime_max}], minFilter: ${minFilter}, dest: ${dstMip}}`);
|
||||
|
||||
gl.drawArrays(gl.POINTS, 0, 1);
|
||||
wtu.glErrorShouldBe(gl, expectError, "after draw with texture");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
var successfullyParsed = true;
|
||||
</script>
|
||||
<script src="../../../js/js-test-post.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -12,6 +12,12 @@ found in the LICENSE.txt file.
|
||||
<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
|
||||
<script src="../../../js/js-test-pre.js"></script>
|
||||
<script src="../../../js/webgl-test-utils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<canvas id="canvas"></canvas>
|
||||
<img id="img" style="display:none;">
|
||||
<script>
|
||||
"use strict";
|
||||
var wtu = WebGLTestUtils;
|
||||
@ -33,7 +39,7 @@ var localImgUrl = "../../../resources/opengl_logo.jpg";
|
||||
var imgDomain;
|
||||
var pageDomain;
|
||||
|
||||
function imageLoaded() {
|
||||
function imageLoaded(img) {
|
||||
description("This test ensures WebGL2 implementations for OffscreenCanvas follow proper same-origin restrictions.");
|
||||
|
||||
if (!window.OffscreenCanvas) {
|
||||
@ -42,8 +48,6 @@ function imageLoaded() {
|
||||
return;
|
||||
}
|
||||
|
||||
var img = this;
|
||||
|
||||
assertMsg(img.width > 0 && img.height > 0, "img was loaded");
|
||||
imgDomain = wtu.getBaseDomain(wtu.getHost(img.src));
|
||||
pageDomain = wtu.getBaseDomain(window.location.host);
|
||||
@ -126,13 +130,17 @@ function imageLoaded() {
|
||||
finishTest();
|
||||
}
|
||||
|
||||
wtu.setupImageForCrossOriginTest("#img", defaultImgUrl, localImgUrl, imageLoaded);
|
||||
(async function() {
|
||||
const img = document.getElementById('img');
|
||||
try {
|
||||
await wtu.awaitOrTimeout(wtu.loadCrossOriginImage(img, defaultImgUrl, localImgUrl), 1000);
|
||||
} catch (e) {
|
||||
testFailed(`Image setup failed (${e}).`);
|
||||
finishTest();
|
||||
return;
|
||||
}
|
||||
imageLoaded(img);
|
||||
})();
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<canvas id="canvas"></canvas>
|
||||
<img id="img" style="display:none;">
|
||||
</body>
|
||||
</html>
|
||||
|
@ -41,7 +41,7 @@ gl.bindTexture(gl.TEXTURE_2D, tex);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB10_A2UI, 16, 16, 0, gl.RGBA_INTEGER, gl.UNSIGNED_INT_2_10_10_10_REV, null);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Teximage2D taking a null array buffer should succeed");
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB10_A2UI, gl.RGBA_INTEGER, gl.UNSIGNED_INT_2_10_10_10_REV, c);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "TexImage2D taking RGB10_A2UI internalformat and a canvas source should fail");
|
||||
wtu.glErrorShouldBe(gl, [gl.INVALID_VALUE, gl.INVALID_ENUM], "TexImage2D taking RGB10_A2UI internalformat and a canvas source should fail");
|
||||
gl.deleteTexture(tex);
|
||||
|
||||
var successfullyParsed = true;
|
||||
|
@ -98,7 +98,7 @@ function runTexCompressedFormatsTest(texCompressedFormats)
|
||||
// Test a 2D texture.
|
||||
var tex = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex);
|
||||
gl.texStorage2D(gl.TEXTURE_2D, 1, internalformat, 1, 1);
|
||||
gl.texStorage2D(gl.TEXTURE_2D, 1, internalformat, 4, 4);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR,
|
||||
"texStorage2D should succeed for " + enumToString(internalformat));
|
||||
gl.deleteTexture(tex);
|
||||
@ -111,14 +111,14 @@ function runTexCompressedFormatsTest(texCompressedFormats)
|
||||
// Test the 3D texture targets.
|
||||
var tex3d = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_3D, tex3d);
|
||||
gl.texStorage3D(gl.TEXTURE_3D, 1, internalformat, 1, 1, 1);
|
||||
gl.texStorage3D(gl.TEXTURE_3D, 1, internalformat, 4, 4, 1);
|
||||
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
|
||||
"texStorage3D(TEXTURE_3D) should fail for " + enumToString(internalformat));
|
||||
gl.deleteTexture(tex3d);
|
||||
|
||||
var tex2dArr = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D_ARRAY, tex2dArr);
|
||||
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, internalformat, 1, 1, 1);
|
||||
gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, internalformat, 4, 4, 1);
|
||||
wtu.glErrorShouldBe(gl, gl.NO_ERROR,
|
||||
"texStorage3D(TEXTURE_2D_ARRAY) should succeed for " + enumToString(internalformat));
|
||||
wtu.clearAndDrawUnitQuad(gl);
|
||||
|
@ -9,6 +9,7 @@ fboinvalidate/00_test_list.txt
|
||||
fborender/00_test_list.txt
|
||||
fragmentoutput/00_test_list.txt
|
||||
framebufferblit/00_test_list.txt
|
||||
multisample/00_test_list.txt
|
||||
primitiverestart/00_test_list.txt
|
||||
shaderindexing/00_test_list.txt
|
||||
shadermatrix/00_test_list.txt
|
||||
@ -43,7 +44,6 @@ instancedrendering.html
|
||||
integerstatequery.html
|
||||
internalformatquery.html
|
||||
lifetime.html
|
||||
multisample.html
|
||||
negativebufferapi.html
|
||||
negativefragmentapi.html
|
||||
negativeshaderapi.html
|
||||
|
@ -1713,7 +1713,7 @@ goog.scope(function() {
|
||||
* Run test
|
||||
* @param {WebGL2RenderingContext} context
|
||||
*/
|
||||
es3fMultisampleTests.run = function(context) {
|
||||
es3fMultisampleTests.run = function(context, range) {
|
||||
gl = context;
|
||||
//Set up Test Root parameters
|
||||
var testName = 'multisample';
|
||||
@ -1730,6 +1730,8 @@ goog.scope(function() {
|
||||
try {
|
||||
//Create test cases
|
||||
es3fMultisampleTests.init();
|
||||
if (range)
|
||||
state.setRange(range);
|
||||
//Run test cases
|
||||
tcuTestCase.runTestCases();
|
||||
}
|
||||
|
@ -1,24 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>WebGL Multisample Conformance Tests</title>
|
||||
<link rel="stylesheet" href="../../../resources/js-test-style.css"/>
|
||||
<script src="../../../js/js-test-pre.js"></script>
|
||||
<script src="../../../js/webgl-test-utils.js"></script>
|
||||
|
||||
<script src="../../../closure-library/closure/goog/base.js"></script>
|
||||
<script src="../../deqp-deps.js"></script>
|
||||
<script>goog.require('functional.gles3.es3fMultisampleTests');</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<canvas id="canvas" width="256" height="256"> </canvas>
|
||||
<script>
|
||||
var wtu = WebGLTestUtils;
|
||||
var gl = wtu.create3DContext('canvas', null, 2);
|
||||
|
||||
functional.gles3.es3fMultisampleTests.run(gl);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,6 @@
|
||||
# This file is auto-generated from multisample_test_generator.py
|
||||
# DO NOT EDIT!
|
||||
default_fbo.html
|
||||
fbo_4_samples.html
|
||||
fbo_8_samples.html
|
||||
fbo_max_samples.html
|
@ -0,0 +1,31 @@
|
||||
<!--
|
||||
|
||||
This file is auto-generated from multisample_test_generator.py
|
||||
DO NOT EDIT!
|
||||
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>WebGL Multisample Conformance Tests</title>
|
||||
<link rel="stylesheet" href="../../../../resources/js-test-style.css"/>
|
||||
<script src="../../../../js/js-test-pre.js"></script>
|
||||
<script src="../../../../js/webgl-test-utils.js"></script>
|
||||
|
||||
<script src="../../../../closure-library/closure/goog/base.js"></script>
|
||||
<script src="../../../deqp-deps.js"></script>
|
||||
<script>goog.require('functional.gles3.es3fMultisampleTests');</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="description"></div>
|
||||
<div id="console"></div>
|
||||
<canvas id="canvas" width="256" height="256"> </canvas>
|
||||
<script>
|
||||
var wtu = WebGLTestUtils;
|
||||
var gl = wtu.create3DContext('canvas', null, 2);
|
||||
|
||||
functional.gles3.es3fMultisampleTests.run(gl, [0, 1]);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user