Bug 703927 - Upgrade WebGL conformance test suite to r16237 - no review

The canonical location for this testsuite is:

  https://cvs.khronos.org/svn/repos/registry/trunk/public/webgl/sdk/tests
This commit is contained in:
Benoit Jacob 2011-12-04 14:15:53 -05:00
parent a959069916
commit bfff5f7f10
44 changed files with 1329 additions and 182 deletions

View File

@ -1,4 +1,4 @@
This is a local copy of the WebGL conformance suite, SVN revision 15981
This is a local copy of the WebGL conformance suite, SVN revision 16237
The canonical location for this testsuite is:

View File

@ -11,13 +11,15 @@ var wtu = WebGLTestUtils;
var canvas;
var gl;
var shouldGenerateGLError;
var extension_name = "WEBKIT_lose_context";
var extension_name = "WEBGL_EXT_lose_context";
var extension;
var bufferObjects;
var program;
var texture;
var texColor = [255, 10, 20, 255];
var allowRestore;
var contextLostEventFired;
var contextRestoredEventFired;
function init()
{
@ -28,15 +30,14 @@ function init()
description("Tests behavior under a restored context.");
shouldGenerateGLError = wtu.shouldGenerateGLError;
runTests();
testLosingContext();
}
function runTests()
function runTest1()
{
testLosingContext();
testLosingAndRestoringContext();
finish();
finishTest();
}
function setupTest()
@ -56,35 +57,75 @@ function setupTest()
function testLosingContext()
{
if (!setupTest())
return;
finishTest();
debug("Test losing a context and inability to restore it.");
canvas.addEventListener("webglcontextlost", testLostContext);
canvas.addEventListener("webglcontextlost", function() {
testLostContext();
// restore the context after this event has exited.
setTimeout(function() {
// we didn't call prevent default so we should not be able to restore the context
shouldGenerateGLError(gl, gl.INVALID_OPERATION, "extension.restoreContext()");
testLosingAndRetoreingContext();
}, 1);
});
canvas.addEventListener("webglcontextrestored", testShouldNotRestoreContext);
allowRestore = false;
contextLostEventFired = false;
contextRestoredEventFired = false;
testOriginalContext();
extension.loseContext();
shouldGenerateGLError(gl, gl.INVALID_OPERATION, "extension.restoreContext()");
debug("");
// The context should be lost immediately.
shouldBeTrue("gl.isContextLost()");
shouldBe("gl.getError()", "gl.CONTEXT_LOST_WEBGL");
shouldBe("gl.getError()", "gl.NO_ERROR");
// gl methods should be no-ops
shouldGenerateGLError(gl, gl.NO_ERROR, gl.blendFunc(gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP));
// but the event should not have been fired.
shouldBeFalse("contextLostEventFired");
}
function testLosingAndRestoringContext()
{
if (!setupTest())
return;
finishTest();
debug("");
debug("Test losing and restoring a context.");
canvas.addEventListener("webglcontextlost", testLostContext);
canvas.addEventListener("webglcontextrestored", testRestoredContext);
canvas.addEventListener("webglcontextlost", function() {
testLostContext();
// restore the context after this event has exited.
setTimeout(function() {
shouldGenerateGLError(gl, gl.NO_ERROR, "extension.restoreContext()");
// The context should still be lost. It will not get restored until the
// webglrestorecontext event is fired.
shouldBeTrue("gl.isContextLost()");
shouldBe("gl.getError()", "gl.NO_ERROR");
// gl methods should still be no-ops
shouldGenerateGLError(gl, gl.NO_ERROR, gl.blendFunc(gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP));
}, 1);
});
canvas.addEventListener("webglcontextrestored", function() {
testRestoredContext();
finishTest();
});
allowRestore = true;
contextLostEventFired = false;
contextRestoredEventFired = false;
testOriginalContext();
extension.loseContext();
shouldGenerateGLError(gl, gl.NO_ERROR, "extension.restoreContext()");
debug("");
// The context should be lost immediately.
shouldBeTrue("gl.isContextLost()");
shouldBe("gl.getError()", "gl.CONTEXT_LOST_WEBGL");
shouldBe("gl.getError()", "gl.NO_ERROR");
// gl methods should be no-ops
shouldGenerateGLError(gl, gl.NO_ERROR, gl.blendFunc(gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP));
// but the event should not have been fired.
shouldBeFalse("contextLostEventFired");
}
function testRendering()
@ -118,12 +159,13 @@ function testOriginalContext()
function testLostContext(e)
{
debug("Test lost context");
shouldBeFalse("contextLostEventFired");
contextLostEventFired = true;
shouldBeTrue("gl.isContextLost()");
shouldBe("gl.getError()", "gl.CONTEXT_LOST_WEBGL");
shouldBe("gl.getError()", "gl.NO_ERROR");
debug("");
if (allowRestore)
e.preventDefault();
if (allowRestore)
e.preventDefault();
}
function testShouldNotRestoreContext(e)
@ -147,6 +189,8 @@ function testResources(expected)
function testRestoredContext()
{
debug("Test restored context");
shouldBeFalse("contextRestoredEventFired");
contextRestoredEventFired = true;
shouldBeFalse("gl.isContextLost()");
shouldBe("gl.getError()", "gl.NO_ERROR");
@ -160,16 +204,6 @@ function testRestoredContext()
debug("");
}
function finish() {
successfullyParsed = true;
var epilogue = document.createElement("script");
epilogue.onload = function() {
if (window.nonKhronosFrameworkNotifyDone)
window.nonKhronosFrameworkNotifyDone();
};
epilogue.src = "../../resources/js-test-post.js";
document.body.appendChild(epilogue);
}
</script>
</head>

View File

@ -11,7 +11,7 @@ var wtu;
var canvas;
var gl;
var shouldGenerateGLError;
var extension_name = "WEBKIT_lose_context";
var extension_name = "WEBGL_EXT_lose_context";
var extension;
var buffer;
@ -51,7 +51,7 @@ function init()
extension = gl.getExtension(extension_name);
if (!extension) {
debug(extension_name + " extension not found.");
finish();
finishTest();
return;
}
@ -65,8 +65,8 @@ function loseContext()
debug("");
debug("Lose context");
// Note: this will cause the context to be lost, and the
// webglcontextlost event listener to be called, immediately.
// Note: this will cause the context to be lost, but the
// webglcontextlost event listener to be queued.
shouldGenerateGLError(gl, gl.NO_ERROR, "extension.loseContext()");
debug("");
}
@ -302,19 +302,9 @@ function testLostContext()
debug("");
finish();
finishTest();
}
function finish() {
successfullyParsed = true;
var epilogue = document.createElement("script");
epilogue.onload = function() {
if (window.nonKhronosFrameworkNotifyDone)
window.nonKhronosFrameworkNotifyDone();
};
epilogue.src = "../../resources/js-test-post.js";
document.body.appendChild(epilogue);
}
</script>
</head>
<body onload="init()">

View File

@ -3,4 +3,6 @@ oes-texture-float.html
oes-vertex-array-object.html
webgl-debug-renderer-info.html
webgl-debug-shaders.html
# commented out until 1.0.1 cut
# webgl-experimental-compressed-textures.html

View File

@ -0,0 +1,3 @@
var img_4x4_rgb_dxt1 = [
0xe0,0x07,0x00,0xf8,0x11,0x10,0x15,0x00,
];

View File

@ -0,0 +1,3 @@
var img_4x4_rgba_dxt1 = [
0xe0,0x07,0x00,0xf8,0x13,0x10,0x15,0x00,
];

View File

@ -0,0 +1,3 @@
var img_4x4_rgba_dxt3 = [
0xf6,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xf8,0xe0,0x07,0x44,0x45,0x40,0x55,
];

View File

@ -0,0 +1,3 @@
var img_4x4_rgba_dxt5 = [
0xf6,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xf8,0xe0,0x07,0x44,0x45,0x40,0x55,
];

View File

@ -0,0 +1,3 @@
var img_4x4_rgba_raw = [
0xff,0x00,0x00,0x69,0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,
];

View File

@ -0,0 +1,3 @@
var img_8x8_rgb_dxt1 = [
0xe0,0x07,0x00,0xf8,0x11,0x10,0x15,0x00,0x1f,0x00,0xe0,0xff,0x11,0x10,0x15,0x00,0xe0,0x07,0x1f,0xf8,0x44,0x45,0x40,0x55,0x1f,0x00,0xff,0x07,0x44,0x45,0x40,0x55,
];

View File

@ -0,0 +1,3 @@
var img_8x8_rgba_dxt1 = [
0xe0,0x07,0x00,0xf8,0x13,0x13,0x15,0x00,0x1f,0x00,0xe0,0xff,0x11,0x10,0x15,0x00,0xe0,0x07,0x1f,0xf8,0x44,0x45,0x43,0x57,0x1f,0x00,0xff,0x07,0x44,0x45,0x40,0x55,
];

View File

@ -0,0 +1,3 @@
var img_8x8_rgba_dxt3 = [
0xf6,0xff,0xf6,0xff,0xff,0xff,0xff,0xff,0x00,0xf8,0xe0,0x07,0x44,0x45,0x40,0x55,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0xff,0x1f,0x00,0x44,0x45,0x40,0x55,0xff,0xff,0xff,0xff,0xf6,0xff,0xf6,0xff,0x1f,0xf8,0xe0,0x07,0x11,0x10,0x15,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x1f,0x00,0x11,0x10,0x15,0x00,
];

View File

@ -0,0 +1,3 @@
var img_8x8_rgba_dxt5 = [
0xff,0x69,0x01,0x10,0x00,0x00,0x00,0x00,0x00,0xf8,0xe0,0x07,0x44,0x45,0x40,0x55,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0x1f,0x00,0x44,0x45,0x40,0x55,0xff,0x69,0x00,0x00,0x00,0x01,0x10,0x00,0x1f,0xf8,0xe0,0x07,0x11,0x10,0x15,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x07,0x1f,0x00,0x11,0x10,0x15,0x00,
];

View File

@ -0,0 +1,3 @@
var img_8x8_rgba_pvrtc4bpp = [
0x33,0x30,0x3f,0x00,0xe0,0x83,0x00,0xfc,0xcc,0xcf,0xc0,0xff,0xe0,0x83,0x1f,0xfc,0xcc,0xcf,0xc0,0xff,0xe0,0xff,0x1f,0x80,0x33,0x30,0x3f,0x00,0xfe,0x83,0x1f,0x80,
];

View File

@ -0,0 +1,3 @@
var img_8x8_rgba_raw = [
0xff,0x00,0x00,0x69,0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0x00,0x69,0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0x00,0x69,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0xff,0x00,0xff,0x69,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,
];

View File

@ -0,0 +1,520 @@
<!--
Copyright (c) 2011 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>WebGL WEBGL_EXPERIMENTAL_compressed_textures Conformance Tests</title>
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<style>
img {
border: 1px solid black;
margin-right: 1em;
}
.testimages {
}
.testimages br {
clear: both;
}
.testimages > div {
float: left;
margin: 1em;
}
</style>
<script src="../../resources/desktop-gl-constants.js" type="text/javascript"></script>
<script src="../../resources/js-test-pre.js"></script>
<script src="../resources/webgl-test.js"></script>
<script src="../resources/webgl-test-utils.js"></script>
<script src="compressed-textures/4x4.rgb.dxt1.js"></script>
<script src="compressed-textures/4x4.rgba.dxt1.js"></script>
<script src="compressed-textures/4x4.rgba.dxt5.js"></script>
<script src="compressed-textures/8x8.rgb.dxt1.js"></script>
<script src="compressed-textures/8x8.rgba.dxt1.js"></script>
<script src="compressed-textures/8x8.rgba.dxt5.js"></script>
<script src="compressed-textures/8x8.rgba.pvrtc4bpp.js"></script>
</head>
<body>
<div id="description"></div>
<canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas>
<div id="console"></div>
<!-- Shaders for testing standard derivatives -->
<script>
description("This test verifies the functionality of the OES_vertex_array_object extension, if it is available.");
debug("");
var wtu = WebGLTestUtils;
var canvas = document.getElementById("canvas");
var gl = wtu.create3DContext(canvas, {antialias: false});
var program = wtu.setupTexturedQuad(gl);
var ext = null;
var vao = null;
var validFormats = {
COMPRESSED_RGB_S3TC_DXT1_EXT : 0x83F0,
COMPRESSED_RGBA_S3TC_DXT1_EXT : 0x83F1,
COMPRESSED_RGBA_S3TC_DXT5_EXT : 0x83F3,
ETC1_RGB8_OES : 0x8D64,
COMPRESSED_RGB_PVRTC_4BPPV1_IMG : 0x8C00,
COMPRESSED_RGBA_PVRTC_4BPPV1_IMG : 0x8C02
};
var name;
var supportedFormats;
if (!gl) {
testFailed("WebGL context does not exist");
} else {
testPassed("WebGL context exists");
// Run tests with extension disabled
runTestDisabled();
// Query the extension and store globally so shouldBe can access it
ext = gl.getExtension("WEBGL_EXPERIMENTAL_compressed_textures");
if (!ext) {
testPassed("No WEBGL_EXPERIMENTAL_compressed_textures support -- this is legal");
runSupportedTest(false);
} else {
testPassed("Successfully enabled WEBGL_EXPERIMENTAL_compressed_textures extension");
runSupportedTest(true);
runTestExtension();
}
}
function runSupportedTest(extensionEnabled) {
var supported = gl.getSupportedExtensions();
if (supported.indexOf("WEBGL_EXPERIMENTAL_compressed_textures") >= 0) {
if (extensionEnabled) {
testPassed("WEBGL_EXPERIMENTAL_compressed_textures listed as supported and getExtension succeeded");
} else {
testFailed("WEBGL_EXPERIMENTAL_compressed_textures listed as supported but getExtension failed");
}
} else {
if (extensionEnabled) {
testFailed("WEBGL_EXPERIMENTAL_compressed_textures not listed as supported but getExtension succeeded");
} else {
testPassed("WEBGL_EXPERIMENTAL_compressed_textures not listed as supported and getExtension failed -- this is legal");
}
}
}
function runTestDisabled() {
debug("Testing binding enum with extension disabled");
// Default value is null
if (gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS) === null) {
testPassed("Default value of COMPRESSED_TEXTURE_FORMATS is null");
} else {
testFailed("Default value of COMPRESSED_TEXTURE_FORMATS is not null");
}
}
function checkIsValidFormat(format) {
for (var name in validFormats) {
if (format == validFormats[name]) {
testPassed("supported format " + formatToString(format) + " is valid");
return;
}
}
testFailed("supported format " + formatToString(format) + " is not valid");
}
function formatToString(format) {
for (var p in ext) {
if (ext[p] == format) {
return p;
}
}
return "0x" + format.toString(16);
}
function runTestExtension() {
debug("Testing WEBGL_EXPERIMENTAL_compressed_textures");
// check that all format enums exist.
for (name in validFormats) {
var expected = "0x" + validFormats[name].toString(16);
var actual = "ext['" + name + "']";
shouldBe(actual, expected);
}
supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
// Even if no formats are supported this should return an array.
shouldBeTrue("supportedFormats.length !== undefined");
// check that each format is an allowed format
for (var ii = 0; ii < supportedFormats.length; ++ii) {
checkIsValidFormat(supportedFormats[ii]);
}
// Test each format
for (var ii = 0; ii < supportedFormats.length; ++ii) {
switch (supportedFormats[ii]) {
case ext.COMPRESSED_RGB_S3TC_DXT1_EXT:
testDXT1_RGB();
break;
case ext.COMPRESSED_RGBA_S3TC_DXT1_EXT:
testDXT1_RGBA();
break;
case ext.COMPRESSED_RGBA_S3TC_DXT5_EXT:
testDXT5_RGBA();
break;
case ext.ETC1_RGB8_OES:
testETC1_RGB8();
break;
case ext.COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
testPVRTC_RGB_4BPPV1();
break;
case ext.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
testPVRTC_RGBA_4BPPV1();
break;
}
}
}
function testDXT1_RGB() {
var tests = [
{ width: 4,
height: 4,
channels: 3,
data: img_4x4_rgb_dxt1,
format: ext.COMPRESSED_RGB_S3TC_DXT1_EXT
},
{ width: 8,
height: 8,
channels: 3,
data: img_8x8_rgb_dxt1,
format: ext.COMPRESSED_RGB_S3TC_DXT1_EXT
}
];
testDXTTextures(tests);
}
function testDXT1_RGBA() {
var tests = [
{ width: 4,
height: 4,
channels: 4,
data: img_4x4_rgba_dxt1,
format: ext.COMPRESSED_RGBA_S3TC_DXT1_EXT
},
{ width: 8,
height: 8,
channels: 4,
data: img_8x8_rgba_dxt1,
format: ext.COMPRESSED_RGBA_S3TC_DXT1_EXT
}
];
testDXTTextures(tests);
}
function testDXT5_RGBA() {
var tests = [
{ width: 4,
height: 4,
channels: 4,
data: img_4x4_rgba_dxt5,
format: ext.COMPRESSED_RGBA_S3TC_DXT5_EXT
},
{ width: 8,
height: 8,
channels: 4,
data: img_8x8_rgba_dxt5,
format: ext.COMPRESSED_RGBA_S3TC_DXT5_EXT
}
];
testDXTTextures(tests);
}
function testETC1_RGB8() {
testFailed("ETC1 test not yet implemented");
}
function testPVRTC_RGB_4BPPV1() {
var tests = [
{ width: 8,
height: 8,
channels: 4,
data: img_8x8_rgba_pvrtc4bpp,
format: ext.COMPRESSED_RGB_PVRTC_4BPPV1_IMG
}
];
testPVRTCTextures(tests);
}
function testPVRTC_RGB_4BPPV1() {
var tests = [
{ width: 8,
height: 8,
channels: 4,
data: img_8x8_rgba_pvrtc4bpp,
format: ext.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
}
];
testPVRTCTextures(tests);
}
function testDXTTextures(tests) {
debug("<hr/>");
for (var ii = 0; ii < tests.length; ++ii) {
testDXTTexture(tests[ii]);
}
}
function uncompressDXTBlock(
destBuffer, destX, destY, destWidth, src, srcOffset, format) {
function make565(src, offset) {
return src[offset + 0] + src[offset + 1] * 256;
}
function make8888From565(c) {
return [
Math.floor(((c >> 11) & 0x1F) * 255 / 31),
Math.floor(((c >> 5) & 0x3F) * 255 / 63),
Math.floor(((c >> 0) & 0x1F) * 255 / 31),
255
];
}
function mix(mult, c0, c1, div) {
var r = [];
for (var ii = 0; ii < c0.length; ++ii) {
r[ii] = Math.floor((c0[ii] * mult + c1[ii]) / div);
}
return r;
}
var colorOffset =
srcOffset + ((format == ext.COMPRESSED_RGBA_S3TC_DXT5_EXT) ? 8 : 0);
var color0 = make565(src, colorOffset + 0);
var color1 = make565(src, colorOffset + 2);
var c0gtc1 = color0 > color1 || format == ext.COMPRESSED_RGBA_S3TC_DXT5_EXT;
var rgba0 = make8888From565(color0);
var rgba1 = make8888From565(color1);
var colors = [
rgba0,
rgba1,
c0gtc1 ? mix(2, rgba0, rgba1, 3) : mix(1, rgba0, rgba1, 2),
c0gtc1 ? mix(2, rgba1, rgba0, 3) : [0, 0, 0, 255]
];
// yea I know there is a lot of math in this inner loop.
// so sue me.
for (var yy = 0; yy < 4; ++yy) {
var pixels = src[colorOffset + 4 + yy];
for (var xx = 0; xx < 4; ++xx) {
var dstOff = ((destY + yy) * destWidth + destX + xx) * 4;
var code = (pixels >> (xx * 2)) & 0x3;
var srcColor = colors[code];
var alpha;
switch (format) {
case ext.COMPRESSED_RGB_S3TC_DXT1_EXT:
alpha = 255;
break;
case ext.COMPRESSED_RGBA_S3TC_DXT1_EXT:
alpha = (code == 3 && !c0gtc1) ? 0 : 255;
break;
case ext.COMPRESSED_RGBA_S3TC_DXT5_EXT:
{
var alpha0 = src[srcOffset + 0];
var alpha1 = src[srcOffset + 1];
var alphaOff = Math.floor(yy / 2) * 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 = ((8 - alphaCode) * alpha0 + (alphaCode - 1) * alpha1) / 7;
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 = ((6 - alphaCode) * alpha0 + (alphaCode - 1) * alpha1) / 5;
break;
}
}
}
break;
default:
throw "bad format";
}
destBuffer[dstOff + 0] = srcColor[0];
destBuffer[dstOff + 1] = srcColor[1];
destBuffer[dstOff + 2] = srcColor[2];
destBuffer[dstOff + 3] = alpha;
}
}
}
function uncompressDXT(width, height, data, format) {
if (width % 4 || height % 4) throw "bad width or height";
var dest = new Uint8Array(width * height * 4);
var blocksAcross = width / 4;
var blocksDown = height / 4;
var blockSize = (format == ext.COMPRESSED_RGBA_S3TC_DXT5_EXT ? 16 : 8);
for (var yy = 0; yy < blocksDown; ++yy) {
for (var xx = 0; xx < blocksAcross; ++xx) {
uncompressDXTBlock(
dest, xx * 4, yy * 4, width, data,
(yy * blocksAcross + xx) * blockSize, format);
}
}
return dest;
}
function testDXTTexture(test) {
var uncompressedData = uncompressDXT(
test.width, test.height, test.data, test.format);
var inner = 4; //test.width == 4 ? 4 : 1
for (var ii = 0; ii < inner; ++ii) {
var width = test.width - ii;
var height = test.height - ii;
canvas.width = width;
canvas.height = height;
gl.viewport(0, 0, width, height);
debug("testing " + formatToString(test.format) + " " +
width + "x" + height);
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
ext.compressedTexImage2D(
gl.TEXTURE_2D, 0, test.format, width, height, 0,
new Uint8Array(test.data));
glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture");
wtu.drawQuad(gl);
compareRect(
width, height, test.channels, test.width, test.height, uncompressedData,
test.data, test.format);
}
gl.compressedTexImage2D(
gl.TEXTURE_2D, 0, test.format, width + 1, height, 0,
new Uint8Array(test.data));
glErrorShouldBe(
gl, gl.INVALID_OPERATION, "data size does not match dimensions");
// TODO: test compressedTexSubImage2D
// TODO: test invalid width, height, xoffset, yoffset
}
function insertImg(element, caption, img) {
var div = document.createElement("div");
div.appendChild(img);
var label = document.createElement("div");
label.appendChild(document.createTextNode(caption));
div.appendChild(label);
element.appendChild(div);
}
function makeImage(imageWidth, imageHeight, dataWidth, data, alpha) {
var scale = 8;
var c = document.createElement("canvas");
c.width = imageWidth * scale;
c.height = imageHeight * scale;
var ctx = c.getContext("2d");
for (var yy = 0; yy < imageWidth; ++yy) {
for (var xx = 0; xx < imageHeight; ++xx) {
var offset = (yy * dataWidth + xx) * 4;
ctx.fillStyle = "rgba(" +
data[offset + 0] + "," +
data[offset + 1] + "," +
data[offset + 2] + "," +
(alpha ? data[offset + 3] / 255 : 1) + ")";
ctx.fillRect(xx * scale, yy * scale, scale, scale);
}
}
var img = document.createElement("img");
img.src = c.toDataURL();
return img;
}
function compareRect(
actualWidth, actualHeight, actualChannels,
dataWidth, dataHeight, expectedData,
testData, testFormat) {
var actual = new Uint8Array(actualWidth * actualHeight * 4);
gl.readPixels(
0, 0, actualWidth, actualHeight, gl.RGBA, gl.UNSIGNED_BYTE, actual);
var div = document.createElement("div");
div.className = "testimages";
insertImg(div, "expected", makeImage(
actualWidth, actualHeight, dataWidth, expectedData,
actualChannels == 4));
insertImg(div, "actual", makeImage(
actualWidth, actualHeight, actualWidth, actual,
actualChannels == 4));
div.appendChild(document.createElement('br'));
document.getElementById("console").appendChild(div);
var failed = false;
for (var yy = 0; yy < actualHeight; ++yy) {
for (var xx = 0; xx < actualWidth; ++xx) {
var actualOffset = (yy * actualWidth + xx) * 4;
var expectedOffset = (yy * dataWidth + xx) * 4;
var expected = [
expectedData[expectedOffset + 0],
expectedData[expectedOffset + 1],
expectedData[expectedOffset + 2],
(actualChannels == 3 ? 255 : expectedData[expectedOffset + 3])
];
for (var jj = 0; jj < 4; ++jj) {
if (actual[actualOffset + jj] != expected[jj]) {
failed = true;
var was = actual[actualOffset + 0].toString();
for (j = 1; j < 4; ++j) {
was += "," + actual[actualOffset + j];
}
testFailed('at (' + xx + ', ' + yy +
') expected: ' + expected + ' was ' + was);
}
}
}
}
if (!failed) {
testPassed("texture rendered correctly");
}
}
function testPVRTCTextures() {
testFailed("PVRTC test not yet implemented");
}
debug("");
successfullyParsed = true;
</script>
<script src="../../resources/js-test-post.js"></script>
</body>
</html>

View File

@ -25,6 +25,7 @@ GLSLGenerator.runFeatureTest({
args: "$(type) p1, $(type) p2",
baseArgs: "value$(field)",
testFunc: "$(func)($(type),$(type))",
fragmentTolerance: 1,
emuFuncs: [
{ type: "float",
code: [

View File

@ -25,6 +25,7 @@ GLSLGenerator.runFeatureTest({
args: "$(type) value",
baseArgs: "value$(field)",
testFunc: "$(func)($(type))",
fragmentTolerance: 1,
emuFuncs: [
{ type: "float",
code: [

View File

@ -24,6 +24,7 @@ GLSLGenerator.runFeatureTest({
args: "$(type) value, float divisor",
baseArgs: "value$(field), divisor",
testFunc: "$(func)($(arg0), float)",
fragmentTolerance: 1,
emuFunc: ["float $(func)_base(float value, float divisor) {",
" return value - divisor * floor(value / divisor);",
"}"].join("\n"),

View File

@ -32,6 +32,7 @@ var fragmentShader = wtu.loadStandardFragmentShader(gl);
assertMsg(fragmentShader, "fragment shader loaded");
var program = gl.createProgram();
shouldBeTrue("program != null");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.attachShader(program, vertexShader)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.attachShader(program, fragmentShader)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.linkProgram(program)");
@ -56,13 +57,18 @@ debug("");
debug("texture deletion");
var fbo = gl.createFramebuffer(), fbo2 = gl.createFramebuffer(), fbo3 = gl.createFramebuffer();
shouldBeTrue("fbo != null");
shouldBeTrue("fbo2 != null");
shouldBeTrue("fbo3 != null");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
var tex = gl.createTexture();
shouldBeTrue("tex != null");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, tex)");
shouldBe("gl.getParameter(gl.TEXTURE_BINDING_2D)", "tex");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0)");
shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)", "tex");
shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)", "gl.TEXTURE");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteTexture(tex)");
// Deleting a texture bound to the currently-bound fbo is the same as
// detaching the textue from fbo first, then delete the texture.
@ -74,6 +80,7 @@ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, tex)");
shouldBeNull("gl.getParameter(gl.TEXTURE_BINDING_2D)");
var texCubeMap = gl.createTexture();
shouldBeTrue("texCubeMap != null");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_CUBE_MAP, texCubeMap)");
shouldBe("gl.getParameter(gl.TEXTURE_BINDING_CUBE_MAP)", "texCubeMap");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteTexture(texCubeMap)");
@ -83,16 +90,33 @@ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_CUBE_MAP, texC
shouldBeNull("gl.getParameter(gl.TEXTURE_BINDING_CUBE_MAP)");
var t = gl.createTexture();
shouldBeTrue("t != null");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, t)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteTexture(t)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, t)");
shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)");
var t2 = gl.createTexture();
shouldBeTrue("t2 != null");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.activeTexture(gl.TEXTURE0)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, t2)");
shouldBe("gl.getParameter(gl.TEXTURE_BINDING_2D)", "t2");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.activeTexture(gl.TEXTURE1)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, t2)");
shouldBe("gl.getParameter(gl.TEXTURE_BINDING_2D)", "t2");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteTexture(t2)");
shouldBeNull("gl.getParameter(gl.TEXTURE_BINDING_2D)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.activeTexture(gl.TEXTURE0)");
shouldBeNull("gl.getParameter(gl.TEXTURE_BINDING_2D)");
debug("");
debug("renderbuffer deletion");
var rbo = gl.createRenderbuffer(), rbo2 = gl.createRenderbuffer(), rbo3 = gl.createRenderbuffer();
shouldBeTrue("rbo != null");
shouldBeTrue("rbo2 != null");
shouldBeTrue("rbo3 != null");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, rbo)");
shouldBe("gl.getParameter(gl.RENDERBUFFER_BINDING)", "rbo");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo)");
@ -111,10 +135,179 @@ shouldBe("gl.getParameter(gl.RENDERBUFFER_BINDING)", "rbo2");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteRenderbuffer(rbo3)");
shouldBe("gl.getParameter(gl.RENDERBUFFER_BINDING)", "rbo2");
debug("");
debug("using deleted renderbuffer");
rbo = gl.createRenderbuffer();
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, rbo)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo)");
if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
// make backbuffer red
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(1,0,0,1)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
// make fbo green
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,1,0,1)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
// Bind backbuffer.
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
// delete renderbuffer. It should still be attached to fbo though.
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteRenderbuffer(rbo)");
shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [255,0,0,255], "backbuffer should be red")');
// Use fbo that has deleted rbo.
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [0,255,0,255], "fbo should be green")');
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,0,1,1)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [0,0,255,255], "fbo should be blue")');
// Bind backbuffer.
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [255,0,0,255], "backbuffer should be red")');
}
debug("");
debug("renderbuffer attached twice to same framebuffer");
rbo = gl.createRenderbuffer();
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, rbo)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo)");
if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
var rbo2 = gl.createRenderbuffer();
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, rbo2)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16)");
// attach rbo2 at two attachment points incompatible with it
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rbo2)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, rbo2)");
shouldBeTrue("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) == rbo2");
shouldBeTrue("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) == rbo2");
// fbo can't be complete as rbo2 is attached at incompatible attachment points
shouldBeFalse("gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE");
// now we delete rbo2, which detaches it from the two attachment points where it currently is attached
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteRenderbuffer(rbo2)");
shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)", "gl.NONE");
shouldBe("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)", "gl.NONE");
// we should now be in the same state as before with only rbo attached, so fbo should be complete again
shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
shouldBeTrue("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) == rbo");
}
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteRenderbuffer(rbo)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
debug("");
debug("using deleted texture");
tex = gl.createTexture();
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, tex)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null)");
if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
// make fbo green
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,1,0,1)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
// Bind backbuffer.
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
// delete texture. It should still be attached to fbo though.
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteTexture(tex)");
shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 1, 1, [255,0,0,255], "backbuffer should be red")');
// Use fbo that has deleted texture.
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0,255,0,255], "fbo should be green")');
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,0,1,1)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0,0,255,255], "fbo should be blue")');
// Bind backbuffer.
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [255,0,0,255], "backbuffer should be red")');
}
debug("");
debug("using deleted renderbuffer");
rbo = gl.createRenderbuffer();
shouldBeTrue("rbo != null");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, rbo)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo)");
if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo)");
shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
// make backbuffer red
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(1,0,0,1)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
// make fbo green
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,1,0,1)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
// delete renderbuffer. It should still be attached to fbo2 though.
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteRenderbuffer(rbo)");
// fbo has no attachments
shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE");
// Use fbo2 that has deleted rbo.
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2)");
shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [0,255,0,255], "fbo should be green")');
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,0,1,1)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [0,0,255,255], "fbo should be blue")');
shouldBeTrue("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) == rbo");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)");
shouldGenerateGLError(gl, gl.NONE, "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)");
shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE");
// Bind backbuffer.
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [255,0,0,255], "backbuffer should be red")');
}
debug("");
debug("using deleted texture");
tex = gl.createTexture();
shouldBeTrue("tex != null");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindTexture(gl.TEXTURE_2D, tex)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null)");
if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0)");
// make fbo green
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,1,0,1)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
// delete texture. It should still be attached to fbo2 though.
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteTexture(tex)");
// fbo has no attachments
shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE");
// Use fbo that has deleted texture.
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2)");
shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE");
shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0,255,0,255], "fbo should be green")');
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,0,1,1)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0,0,255,255], "fbo should be blue")');
shouldBeTrue("gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) == tex");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)");
shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE");
// Bind backbuffer.
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [255,0,0,255], "backbuffer should be red")');
}
debug("");
debug("buffer deletion");
var buffer = gl.createBuffer();
shouldBeTrue("buffer != null");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, buffer)");
shouldBe("gl.getParameter(gl.ARRAY_BUFFER_BINDING)", "buffer");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteBuffer(buffer)");
@ -123,7 +316,19 @@ shouldBeNull("gl.getParameter(gl.ARRAY_BUFFER_BINDING)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, buffer)");
shouldBeNull("gl.getParameter(gl.ARRAY_BUFFER_BINDING)");
var buffer2 = gl.createBuffer();
shouldBeTrue("buffer2 != null");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, buffer2)");
shouldBe("gl.getParameter(gl.ARRAY_BUFFER_BINDING)", "buffer2");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, null)");
shouldBeNull("gl.getParameter(gl.ARRAY_BUFFER_BINDING)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteBuffer(buffer2)");
shouldBeFalse("gl.isBuffer(buffer2)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, buffer2)");
shouldBeNull("gl.getParameter(gl.ARRAY_BUFFER_BINDING)");
var bufferElement = gl.createBuffer();
shouldBeTrue("bufferElement != null");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufferElement)");
shouldBe("gl.getParameter(gl.ELEMENT_ARRAY_BUFFER_BINDING)", "bufferElement");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteBuffer(bufferElement)");
@ -133,12 +338,35 @@ shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, b
shouldBeNull("gl.getParameter(gl.ELEMENT_ARRAY_BUFFER_BINDING)");
var b = gl.createBuffer();
shouldBeTrue("b != null");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, b)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bufferData(gl.ARRAY_BUFFER, 1, gl.STATIC_DRAW)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteBuffer(b)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, b)");
shouldGenerateGLError(gl, gl.INVALID_OPERATION, "gl.bufferData(gl.ARRAY_BUFFER, 1, gl.STATIC_DRAW)");
var b1 = gl.createBuffer();
shouldBeTrue("b1 != null");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, b1);");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.enableVertexAttribArray(1);");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.vertexAttribPointer(1, 4, gl.FLOAT, false, 0, 0);");
var b2 = gl.createBuffer();
shouldBeTrue("b2 != null");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindBuffer(gl.ARRAY_BUFFER, b2);");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.enableVertexAttribArray(2);");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.vertexAttribPointer(2, 4, gl.FLOAT, false, 0, 0);");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.enableVertexAttribArray(3);");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.vertexAttribPointer(3, 4, gl.FLOAT, false, 0, 0);");
shouldBe("gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)", "b1");
shouldBe("gl.getVertexAttrib(2, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)", "b2");
shouldBe("gl.getVertexAttrib(3, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)", "b2");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteBuffer(b2);");
shouldBe("gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)", "b1");
shouldBeNull("gl.getVertexAttrib(2, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)");
shouldBeNull("gl.getVertexAttrib(3, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteBuffer(b1);");
shouldBeNull("gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)");
debug("");
debug("framebuffer deletion");
@ -154,6 +382,41 @@ shouldBe("gl.getParameter(gl.FRAMEBUFFER_BINDING)", "fbo2");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteFramebuffer(fbo3)");
shouldBe("gl.getParameter(gl.FRAMEBUFFER_BINDING)", "fbo2");
fbo = gl.createFramebuffer();
rbo = gl.createRenderbuffer();
shouldBeTrue("fbo != null");
shouldBeTrue("rbo != null");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindRenderbuffer(gl.RENDERBUFFER, rbo)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo)");
if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE) {
// set backbuffer to red
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(1,0,0,1)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
// set framebuffer to green
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, fbo)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,1,0,1)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
// check framebuffer
shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 16, 16, [0,255,0,255], "fbo should be green")');
shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 16, 16, 1, 1, [0,0,0,0], "outside fbo should be black")');
// delete framebuffer. because this was the bound fbo the backbuffer should be active now
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.deleteFramebuffer(fbo)");
// check backbuffer
shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 300, 150, [255,0,0,255], "backbuffer should be red")');
shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 300, 0, 300, 300, [0,0,0,0], "outside backbuffer should be black")');
shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 150, 300, 300, [0,0,0,0], "outside backbuffer should be black")');
// check drawing to backbuffer
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clearColor(0,1,0,1)");
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.clear(gl.COLOR_BUFFER_BIT)");
shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 300, 150, [0,255,0,255], "fbo should be green")');
shouldGenerateGLError(gl, gl.NO_ERROR, "gl.bindFramebuffer(gl.FRAMEBUFFER, null)");
// check again because many buggy implementations will have bound to the true backbuffer on deleteFramebuffer.
shouldGenerateGLError(gl, gl.NO_ERROR, 'wtu.checkCanvasRect(gl, 0, 0, 300, 150, [0,255,0,255], "fbo should be green")');
}
successfullyParsed = true;
</script>

View File

@ -59,7 +59,7 @@ uniform vec4 foo;
varying vec4 texCoord0;
void main()
{
gl_FragColor = vec4(foo.r/256.0, foo.g/256.0, foo.b/256.0, foo.a*texCoord0.z/256.0);
gl_FragColor = vec4(foo.r/255.0, foo.g/255.0, foo.b/255.0, foo.a*texCoord0.z/255.0);
}
</script>
<style>canvas{ position:absolute; }</style>

View File

@ -82,10 +82,10 @@ varying vec4 texCoord0;
void main()
{
gl_FragColor = vec4(
uniV4[0].r/256.0,
uniV4[0].g/256.0,
uniV4[0].b/256.0,
uniV4[0].a*texCoord0.z/256.0);
uniV4[0].r/255.0,
uniV4[0].g/255.0,
uniV4[0].b/255.0,
uniV4[0].a*texCoord0.z/255.0);
}
</script>
<style>canvas{ position:absolute; }</style>

View File

@ -87,10 +87,10 @@ varying vec4 texCoord0;
void main()
{
gl_FragColor = vec4(
uniV4.r/256.0,
uniV4.g/256.0,
uniV4.b/256.0,
uniV4.a*texCoord0.z/256.0);
uniV4.r/255.0,
uniV4.g/255.0,
uniV4.b/255.0,
uniV4.a*texCoord0.z/255.0);
}
</script>
<style>canvas{ position:absolute; }</style>

View File

@ -27,29 +27,43 @@ var colorBuffer;
var width;
var height;
function testAttachment(attachment, buffer, isConflicted)
const ALLOW_COMPLETE = 0x01;
const ALLOW_UNSUPPORTED = 0x02;
const ALLOW_INCOMPLETE_ATTACHMENT = 0x04;
function CheckFramebufferForAllowedStatuses(allowedStatuses)
{
// If the framebuffer is in an error state for multiple reasons,
// we can't guarantee which one will be reported.
var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
var statusAllowed = ((allowedStatuses & ALLOW_COMPLETE) && (status == gl.FRAMEBUFFER_COMPLETE)) ||
((allowedStatuses & ALLOW_UNSUPPORTED) && (status == gl.FRAMEBUFFER_UNSUPPORTED)) ||
((allowedStatuses & ALLOW_INCOMPLETE_ATTACHMENT) && (status == gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT));
var msg = "gl.checkFramebufferStatus(gl.FRAMEBUFFER) returned " + status;
if (statusAllowed)
testPassed(msg);
else
testFailed(msg);
}
function testAttachment(attachment, buffer, allowedStatuses)
{
shouldBeNonNull("fbo = gl.createFramebuffer()");
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, buffer);
glErrorShouldBe(gl, gl.NO_ERROR);
// If the framebuffer is in an error state for multiple reasons,
// we can't guarantee which one will be reported.
if ((width == 0 || height == 0) && !isConflicted) {
// Zero-sized renderbuffers are supposed to result in an incomplete attachment.
// However, certain combination may violate implementation specific restrictions.
shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT || gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_UNSUPPORTED");
} else if (isConflicted) {
shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_UNSUPPORTED");
CheckFramebufferForAllowedStatuses(allowedStatuses);
if ((allowedStatuses & ALLOW_COMPLETE) == 0) {
gl.clear(gl.COLOR_BUFFER_BIT);
glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(width * height * 4));
glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION);
}
gl.deleteFramebuffer(fbo);
}
function testAttachments(attachment0, buffer0, attachment1, buffer1, isConflicted)
function testAttachments(attachment0, buffer0, attachment1, buffer1, allowedStatuses)
{
shouldBeNonNull("fbo = gl.createFramebuffer()");
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
@ -58,27 +72,20 @@ function testAttachments(attachment0, buffer0, attachment1, buffer1, isConflicte
glErrorShouldBe(gl, gl.NO_ERROR);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment1, gl.RENDERBUFFER, buffer1);
glErrorShouldBe(gl, gl.NO_ERROR);
// If the framebuffer is in an error state for multiple reasons,
// we can't guarantee which one will be reported.
if ((width == 0 || height == 0) && !isConflicted) {
// Zero-sized renderbuffers are supposed to result in an incomplete attachment.
// However, certain combination may violate implementation specific restrictions.
shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT || gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_UNSUPPORTED");
} else if (isConflicted) {
shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_UNSUPPORTED");
}
CheckFramebufferForAllowedStatuses(allowedStatuses);
gl.deleteFramebuffer(fbo);
}
function testColorRenderbuffer(internalformat)
function testColorRenderbuffer(internalformat, allowedStatuses)
{
shouldBeNonNull("colorBuffer = gl.createRenderbuffer()");
gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer);
gl.renderbufferStorage(gl.RENDERBUFFER, internalformat, width, height);
glErrorShouldBe(gl, gl.NO_ERROR);
testAttachment(gl.COLOR_ATTACHMENT0, colorBuffer, false);
testAttachment(gl.COLOR_ATTACHMENT0, colorBuffer, allowedStatuses);
}
function testDepthStencilRenderbuffer()
function testDepthStencilRenderbuffer(allowedStatuses)
{
shouldBeNonNull("depthStencilBuffer = gl.createRenderbuffer()");
gl.bindRenderbuffer(gl.RENDERBUFFER, depthStencilBuffer);
@ -103,7 +110,7 @@ function testDepthStencilRenderbuffer()
shouldBeTrue("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_STENCIL_SIZE) > 0");
}
glErrorShouldBe(gl, gl.NO_ERROR);
testAttachment(gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, false);
testAttachment(gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, allowedStatuses);
}
description("Test framebuffer object attachment behaviors");
@ -134,49 +141,59 @@ for (width = 0; width <= 2; width += 2)
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height);
glErrorShouldBe(gl, gl.NO_ERROR);
var allowedStatusForGoodCase
= (width == 0 || height == 0) ? ALLOW_INCOMPLETE_ATTACHMENT : ALLOW_COMPLETE;
// some cases involving stencil seem to be implementation-dependent
var allowedStatusForImplDependentCase = allowedStatusForGoodCase | ALLOW_UNSUPPORTED;
debug("Attach depth using DEPTH_ATTACHMENT");
testAttachment(gl.DEPTH_ATTACHMENT, depthBuffer, false);
testAttachment(gl.DEPTH_ATTACHMENT, depthBuffer, allowedStatusForGoodCase);
debug("Attach depth using STENCIL_ATTACHMENT");
testAttachment(gl.STENCIL_ATTACHMENT, depthBuffer, true);
testAttachment(gl.STENCIL_ATTACHMENT, depthBuffer, ALLOW_INCOMPLETE_ATTACHMENT);
debug("Attach depth using DEPTH_STENCIL_ATTACHMENT");
testAttachment(gl.DEPTH_STENCIL_ATTACHMENT, depthBuffer, true);
testAttachment(gl.DEPTH_STENCIL_ATTACHMENT, depthBuffer, ALLOW_INCOMPLETE_ATTACHMENT);
debug("Attach stencil using STENCIL_ATTACHMENT");
testAttachment(gl.STENCIL_ATTACHMENT, stencilBuffer, false);
testAttachment(gl.STENCIL_ATTACHMENT, stencilBuffer, allowedStatusForImplDependentCase);
debug("Attach stencil using DEPTH_ATTACHMENT");
testAttachment(gl.DEPTH_ATTACHMENT, stencilBuffer, true);
testAttachment(gl.DEPTH_ATTACHMENT, stencilBuffer, ALLOW_INCOMPLETE_ATTACHMENT);
debug("Attach stencil using DEPTH_STENCIL_ATTACHMENT");
testAttachment(gl.DEPTH_STENCIL_ATTACHMENT, stencilBuffer, true);
testAttachment(gl.DEPTH_STENCIL_ATTACHMENT, stencilBuffer, ALLOW_INCOMPLETE_ATTACHMENT);
debug("Attach depthStencil using DEPTH_STENCIL_ATTACHMENT");
testAttachment(gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, false);
testAttachment(gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, allowedStatusForGoodCase);
debug("Attach depthStencil using DEPTH_ATTACHMENT");
testAttachment(gl.DEPTH_ATTACHMENT, depthStencilBuffer, true);
testAttachment(gl.DEPTH_ATTACHMENT, depthStencilBuffer, ALLOW_INCOMPLETE_ATTACHMENT);
debug("Attach depthStencil using STENCIL_ATTACHMENT");
testAttachment(gl.STENCIL_ATTACHMENT, depthStencilBuffer, true);
testAttachment(gl.STENCIL_ATTACHMENT, depthStencilBuffer, ALLOW_INCOMPLETE_ATTACHMENT);
var allowedStatusForConflictedAttachment
= (width == 0 || height == 0) ? ALLOW_UNSUPPORTED | ALLOW_INCOMPLETE_ATTACHMENT
: ALLOW_UNSUPPORTED;
debug("Attach depth, then stencil, causing conflict");
testAttachments(gl.DEPTH_ATTACHMENT, depthBuffer, gl.STENCIL_ATTACHMENT, stencilBuffer, true);
testAttachments(gl.DEPTH_ATTACHMENT, depthBuffer, gl.STENCIL_ATTACHMENT, stencilBuffer, allowedStatusForConflictedAttachment);
debug("Attach stencil, then depth, causing conflict");
testAttachments(gl.STENCIL_ATTACHMENT, stencilBuffer, gl.DEPTH_ATTACHMENT, depthBuffer, true);
testAttachments(gl.STENCIL_ATTACHMENT, stencilBuffer, gl.DEPTH_ATTACHMENT, depthBuffer, allowedStatusForConflictedAttachment);
debug("Attach depth, then depthStencil, causing conflict");
testAttachments(gl.DEPTH_ATTACHMENT, depthBuffer, gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, true);
testAttachments(gl.DEPTH_ATTACHMENT, depthBuffer, gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, allowedStatusForConflictedAttachment);
debug("Attach depthStencil, then depth, causing conflict");
testAttachments(gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, gl.DEPTH_ATTACHMENT, depthBuffer, true);
testAttachments(gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, gl.DEPTH_ATTACHMENT, depthBuffer, allowedStatusForConflictedAttachment);
debug("Attach stencil, then depthStencil, causing conflict");
testAttachments(gl.DEPTH_ATTACHMENT, depthBuffer, gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, true);
testAttachments(gl.DEPTH_ATTACHMENT, depthBuffer, gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, allowedStatusForConflictedAttachment);
debug("Attach depthStencil, then stencil, causing conflict");
testAttachments(gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, gl.STENCIL_ATTACHMENT, stencilBuffer, true);
testAttachments(gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, gl.STENCIL_ATTACHMENT, stencilBuffer, allowedStatusForConflictedAttachment);
debug("Attach color renderbuffer with internalformat == RGBA4");
testColorRenderbuffer(gl.RGBA4);
testColorRenderbuffer(gl.RGBA4, allowedStatusForGoodCase);
debug("Attach color renderbuffer with internalformat == RGB5_A1");
testColorRenderbuffer(gl.RGB5_A1);
testColorRenderbuffer(gl.RGB5_A1, allowedStatusForGoodCase);
debug("Attach color renderbuffer with internalformat == RGB565");
testColorRenderbuffer(gl.RGB565);
testColorRenderbuffer(gl.RGB565, allowedStatusForGoodCase);
debug("Create and attach depthStencil renderbuffer");
testDepthStencilRenderbuffer();
testDepthStencilRenderbuffer(allowedStatusForGoodCase);
}
}
@ -266,23 +283,35 @@ function testUsingIncompleteFramebuffer() {
debug("Drawing or reading from an incomplete framebuffer should generate INVALID_FRAMEBUFFER_OPERATION");
testRenderingAndReading();
shouldBeNonNull("fbo = gl.createFramebuffer()");
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
shouldBeNonNull("fbo2 = gl.createFramebuffer()");
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2);
CheckFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);
debug("");
debug("Drawing or reading from an incomplete framebuffer should generate INVALID_FRAMEBUFFER_OPERATION");
testRenderingAndReading();
shouldBeNonNull("colorBuffer = gl.createRenderbuffer()");
gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer);
gl.framebufferRenderbuffer(
gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 0, 0);
debug("");
debug("Drawing or reading from an incomplete framebuffer should generate INVALID_FRAMEBUFFER_OPERATION");
testRenderingAndReading();
function testRenderingAndReading() {
glErrorShouldBe(gl, gl.NO_ERROR);
wtu.drawQuad(gl);
glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "drawArrays with incomplete framebuffer");
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4));
glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "readPixels from incomplete framebuffer");
// copyTexImage and copyTexSubImage can be either INVALID_FRAMEBUFFER_OPERATION because
// the framebuffer is invalid OR INVALID_OPERATION because in the case of no attachments
// the framebuffer is not of a compatible type.
gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "copyTexImage2D from incomplete framebuffer");
glErrorShouldBe(gl, [gl.INVALID_FRAMEBUFFER_OPERATION, gl.INVALID_OPERATION], "copyTexImage2D from incomplete framebuffer");
gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 1, 1, 0);
glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "copyTexSubImage2D from incomplete framebuffer");
glErrorShouldBe(gl, [gl.INVALID_FRAMEBUFFER_OPERATION, gl.INVALID_OPERATION], "copyTexSubImage2D from incomplete framebuffer");
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "clear with incomplete framebuffer");
}

View File

@ -6,4 +6,4 @@ gl-scissor-test.html
more-than-65536-indices.html
point-size.html
triangle.html
line-loop-tri-fan.html

View File

@ -0,0 +1,238 @@
<!--
Copyright (C) 2011 Opera Software ASA. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY OPERA SOFTWARE ASA. ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../resources/js-test-pre.js"></script>
<script src="../resources/webgl-test.js"></script>
<script id="vshader" type="x-shader/x-vertex">
attribute vec2 pos;
void main()
{
gl_Position = vec4(pos, 0, 1);
}
</script>
<script id="fshader" type="x-shader/x-fragment">
precision mediump float;
void main()
{
gl_FragColor = vec4(0, 1, 0, 1);
}
</script>
<script>
// Check a single 32-bit RGBA pixel.
function checkPixel(buf, index, correct) {
for (var i = 0; i < 4; ++i) {
if (buf[index + i] != correct[i]) {
return false;
}
}
return true;
}
// Check the line loop by reading the pixels and making sure just the edge
// pixels are green and the rest are black.
function checkLineLoop(gl, w) {
var buf = new Uint8Array(w * w * 4);
gl.readPixels(0, 0, w, w, gl.RGBA, gl.UNSIGNED_BYTE, buf);
var green = [0,255,0,255];
var black = [0,0,0,255];
var isCorrect = true;
for (var j = 0; j < w * w * 4; j += 4) {
var correct = black;
if (j < w * 4 || j > w * (w - 1) * 4 || j % (w * 4) == 0 || j % (w * 4) == (w - 1) * 4) {
correct = green;
}
if (!checkPixel(buf, j, correct)) {
isCorrect = false;
break;
}
}
if (isCorrect) {
testPassed("Line loop was drawn correctly.");
} else {
testFailed("Line loop was drawn incorrectly.");
}
}
// Check the tri fan by reading the pixels and making sure they are all green.
function checkTriFan(gl, w) {
buf = new Uint8Array(w * w * 4);
gl.readPixels(0, 0, w, w, gl.RGBA, gl.UNSIGNED_BYTE, buf);
var filled = true;
for (var j = 0; j < w * w * 4; j += 4) {
if (!checkPixel(buf, j, [0,255,0,255])) {
filled = false;
break;
}
}
if (filled) {
testPassed("Triangle fan was drawn correctly.");
} else {
testFailed("Triangle fan was drawn incorrectly.");
}
}
function runTest()
{
var gl = initWebGL('testbed', 'vshader', 'fshader', ['pos'], [0, 0, 0, 1], 1, { antialias: false });
if (!gl) {
testFailed('initWebGL(..) failed');
return;
}
var w = document.getElementById('testbed').width;
gl.enableVertexAttribArray(0);
//---------- LINE_LOOP----------
var d = 1/w;
var vertices = new Float32Array([-1+d, -1+d, 1-d, -1+d, 1-d, 1-d, -1+d, 1-d]);
var vertBuf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertBuf);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
var indBuf = gl.createBuffer();
var indices = new Uint16Array([0, 1, 2, 3]);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indBuf);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
debug('Draw a square using a line loop and verify that it draws all four sides and nothing else.');
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.drawArrays(gl.LINE_LOOP, 0, vertices.length / 2);
checkLineLoop(gl, w);
debug('Draw a square using an indexed line loop and verify that it draws all four sides and nothing else.');
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.drawElements(gl.LINE_LOOP, indices.length, gl.UNSIGNED_SHORT, 0);
checkLineLoop(gl, w);
vertices = new Float32Array([0, 0, 0, 0, 0, 0, -1+d, -1+d, 1-d, -1+d, 1-d, 1-d, -1+d, 1-d]);
vertBuf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertBuf);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
indBuf = gl.createBuffer();
indices = new Uint16Array([0, 1, 2, 3, 4, 5, 6]);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indBuf);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
debug('Draw a square using a line loop with a vertex buffer offset and verify that it draws all four sides and nothing else.');
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.drawArrays(gl.LINE_LOOP, 3, vertices.length / 2 - 3);
checkLineLoop(gl, w);
debug('Draw a square using an indexed line loop with an index buffer offset and verify that it draws all four sides and nothing else.');
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.drawElements(gl.LINE_LOOP, indices.length - 3, gl.UNSIGNED_SHORT, 3 * 2);
checkLineLoop(gl, w);
//---------- LINE_LOOP UBYTE ----------
var degenVerts = new Array(252 * 2);
for (var j = 0; j < 252 * 2; ++j) {
degenVerts[j] = -1+d;
}
degenVerts = degenVerts.concat([-1+d, -1+d, 1-d, -1+d, 1-d, 1-d, -1+d, 1-d]);
vertices = new Float32Array(degenVerts);
vertBuf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertBuf);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
indBuf = gl.createBuffer();
var degenInd = new Array(252);
for (var j = 0; j < 252; ++j) {
degenInd[j] = j;
}
degenInd = degenInd.concat([252, 253, 254, 255]);
indices = new Uint8Array(degenInd);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indBuf);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
debug('Draw a square using an ubyte indexed line loop with 256 indices and verify that it draws all four sides and nothing else.');
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.drawElements(gl.LINE_LOOP, indices.length, gl.UNSIGNED_BYTE, 0);
checkLineLoop(gl, w);
//---------- TRIANGLE_FAN ----------
vertices = new Float32Array([0, 0, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1]);
vertBuf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertBuf);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
indices = new Uint16Array([0,1,2,3,4,5]);
indBuf = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indBuf);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
debug('Draw a filled square using a triangle fan and verify that it fills the entire canvas.');
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLE_FAN, 0, vertices.length / 2);
checkTriFan(gl, w);
debug('Draw a filled square using an indexed triangle fan and verify that it fills the entire canvas.');
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.drawElements(gl.TRIANGLE_FAN, indices.length, gl.UNSIGNED_SHORT, 0);
checkTriFan(gl, w);
vertices = new Float32Array([1, 1, 1, 1, 1, 1, 0, 0, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1]);
vertBuf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertBuf);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
indices = new Uint16Array([0,1,2,3,4,5,6,7,8]);
indBuf = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indBuf);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
debug('Draw a filled square using a triangle fan with a vertex buffer offset and verify that it fills the entire canvas.');
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLE_FAN, 3, vertices.length / 2 - 3);
checkTriFan(gl, w);
debug('Draw a filled square using an indexed triangle fan with an index buffer offset and verify that it fills the entire canvas.');
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.drawElements(gl.TRIANGLE_FAN, indices.length - 3, gl.UNSIGNED_SHORT, 3 * 2);
checkTriFan(gl, w);
}
</script>
</head>
<body>
<canvas id="testbed" width="10px" height="10px" style="width:50px; height:50px"></canvas>
<div id="description"></div>
<div id="console"></div>
<script>
description('Verify that LINE_LOOP and TRIANGLE_FAN works correctly.');
runTest();
successfullyParsed = true;
</script>
<script src="../../resources/js-test-post.js"></script>
</body>
</html>

View File

@ -223,7 +223,10 @@ var runFeatureTest = function(params) {
var wtu = WebGLTestUtils;
var gridRes = params.gridRes;
var tolerance = params.tolerance || 0;
var vertexTolerance = params.tolerance || 0;
var fragmentTolerance = vertexTolerance;
if ('fragmentTolerance' in params)
fragmentTolerance = params.fragmentTolerance || 0;
description("Testing GLSL feature: " + params.feature);
@ -252,13 +255,15 @@ var runFeatureTest = function(params) {
input: "color",
output: "vColor",
vertexShaderTemplate: vertexShaderTemplate,
fragmentShaderTemplate: baseFragmentShader
fragmentShaderTemplate: baseFragmentShader,
tolerance: vertexTolerance
},
{ type: "fragment",
input: "vColor",
output: "gl_FragColor",
vertexShaderTemplate: baseVertexShader,
fragmentShaderTemplate: fragmentShaderTemplate
fragmentShaderTemplate: fragmentShaderTemplate,
tolerance: fragmentTolerance
}
];
for (var ss = 0; ss < shaderInfos.length; ++ss) {
@ -328,7 +333,7 @@ var runFeatureTest = function(params) {
}
var testImg = makeImage(canvas);
reportResults(refData, refImg, testData, testImg);
reportResults(refData, refImg, testData, testImg, shaderInfo.tolerance);
}
}
@ -364,7 +369,7 @@ var runFeatureTest = function(params) {
console.appendChild(div);
}
function reportResults(refData, refImage, testData, testImage) {
function reportResults(refData, refImage, testData, testImage, tolerance) {
var same = true;
for (var yy = 0; yy < height; ++yy) {
for (var xx = 0; xx < width; ++xx) {
@ -487,6 +492,18 @@ return {
* tests:
* The code for each test. It is assumed the tests are for
* float, vec2, vec3, vec4 in that order.
*
* tolerance: (optional)
* Allow some tolerance in the comparisons. The tolerance is applied to
* both vertex and fragment shaders. The default tolerance is 0, meaning
* the values have to be identical.
*
* fragmentTolerance: (optional)
* Specify a tolerance which only applies to fragment shaders. The
* fragment-only tolerance will override the shared tolerance for
* fragment shaders if both are specified. Fragment shaders usually
* use mediump float precision so they sometimes require higher tolerance
* than vertex shaders which use highp.
*/
runFeatureTest: runFeatureTest,

View File

@ -130,18 +130,33 @@ function shouldGenerateGLError(ctx, glErrors, evalStr) {
/**
* Tests that the first error GL returns is the specified error.
* @param {!WebGLContext} gl The WebGLContext to use.
* @param {number} glError The expected gl error.
* @param {number|!Array.<number>} glError The expected gl
* error. Multiple errors can be passed in using an
* array.
* @param {string} opt_msg Optional additional message.
*/
function glErrorShouldBe(gl, glError, opt_msg) {
function glErrorShouldBe(gl, glErrors, opt_msg) {
if (!glErrors.length) {
glErrors = [glErrors];
}
opt_msg = opt_msg || "";
var err = gl.getError();
if (err != glError) {
testFailed("getError expected: " + getGLErrorAsString(gl, glError) +
". Was " + getGLErrorAsString(gl, err) + " : " + opt_msg);
var ndx = glErrors.indexOf(err);
if (ndx < 0) {
if (glErrors.length == 1) {
testFailed("getError expected: " + getGLErrorAsString(gl, glErrors[0]) +
". Was " + getGLErrorAsString(gl, err) + " : " + opt_msg);
} else {
var errs = [];
for (var ii = 0; ii < glErrors.length; ++ii) {
errs.push(getGLErrorAsString(gl, glErrors[ii]));
}
testFailed("getError expected one of: [" + errs.join(", ") +
"]. Was " + getGLErrorAsString(gl, err) + " : " + opt_msg);
}
} else {
testPassed("getError was expected value: " +
getGLErrorAsString(gl, glError) + " : " + opt_msg);
getGLErrorAsString(gl, err) + " : " + opt_msg);
}
};
@ -361,18 +376,18 @@ var getBasePathForResources = function() {
function loadStandardVertexShader(context) {
return loadShader(
context,
getBasePathForResources() + "vertexShader.vert",
context.VERTEX_SHADER,
true);
context,
getBasePathForResources() + "vertexShader.vert",
context.VERTEX_SHADER,
true);
}
function loadStandardFragmentShader(context) {
return loadShader(
context,
getBasePathForResources() + "fragmentShader.frag",
context.FRAGMENT_SHADER,
true);
context,
getBasePathForResources() + "fragmentShader.frag",
context.FRAGMENT_SHADER,
true);
}
//

View File

@ -61,8 +61,8 @@ else {
debug("");
debug("Check default values");
shouldBe('context.getParameter(context.ACTIVE_TEXTURE)', 'context.TEXTURE0');
shouldBe('(context.getParameter(context.ALIASED_LINE_WIDTH_RANGE)[0] == 1) || (context.getParameter(context.ALIASED_LINE_WIDTH_RANGE)[1] == 1)', 'true');
shouldBe('(context.getParameter(context.ALIASED_POINT_SIZE_RANGE)[0] == 1) || (context.getParameter(context.ALIASED_POINT_SIZE_RANGE)[1] == 1)', 'true');
shouldBe('(context.getParameter(context.ALIASED_LINE_WIDTH_RANGE)[0] <= 1) && (context.getParameter(context.ALIASED_LINE_WIDTH_RANGE)[0] > 0) && (context.getParameter(context.ALIASED_LINE_WIDTH_RANGE)[1] >= 1)', 'true');
shouldBe('(context.getParameter(context.ALIASED_POINT_SIZE_RANGE)[0] <= 1) && (context.getParameter(context.ALIASED_POINT_SIZE_RANGE)[0] > 0) && (context.getParameter(context.ALIASED_POINT_SIZE_RANGE)[1] >= 1)', 'true');
shouldBe('context.getParameter(context.ARRAY_BUFFER_BINDING)', 'null');
shouldBe('context.getParameter(context.BLEND)', 'false');
shouldBe('context.getParameter(context.BLEND_COLOR)', '[0, 0, 0, 0]');

View File

@ -22,6 +22,7 @@ description("Test texImage2D conversions.");
var wtu = WebGLTestUtils;
var canvas = document.getElementById("example");
var gl = wtu.create3DContext(canvas);
gl.disable(gl.DITHER);
var program = wtu.setupTexturedQuad(gl);
glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");

View File

@ -46,6 +46,7 @@ function init()
var canvas = document.getElementById("example");
gl = wtu.create3DContext(canvas);
gl.disable(gl.DITHER);
var program = wtu.setupTexturedQuad(gl);
gl.clearColor(0,0,0,1);

View File

@ -35,6 +35,7 @@ description('Tests texSubImage2D upload path from Uint8Array');
var wtu = WebGLTestUtils;
var canvas = document.getElementById("example");
var gl = wtu.create3DContext(canvas);
gl.disable(gl.DITHER);
var program = wtu.setupProgram(
gl,
[wtu.setupSimpleTextureVertexShader(gl),

View File

@ -211,12 +211,17 @@ function checkRect(x, y, width, height, color) {
function fillLevel(target, level, size, color) {
var numPixels = size * size;
var pixels = new Uint8Array(numPixels * 4);
for (var jj = 0; jj < numPixels; ++jj) {
var pixelRow = new Uint8Array(size * 4);
for (var jj = 0; jj < size; ++jj) {
var off = jj * 4;
pixels[off + 0] = color[0];
pixels[off + 1] = color[1];
pixels[off + 2] = color[2];
pixels[off + 3] = color[3];
pixelRow[off + 0] = color[0];
pixelRow[off + 1] = color[1];
pixelRow[off + 2] = color[2];
pixelRow[off + 3] = color[3];
}
for (var jj = 0; jj < size; ++jj) {
var off = jj * size * 4;
pixels.set(pixelRow, off);
}
gl.texImage2D(
target, level, gl.RGBA, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE,

View File

@ -14,7 +14,7 @@ found in the LICENSE file.
<script src="../resources/webgl-test-utils.js"></script>
</head>
<body>
<canvas id="example" width="256" height="256" style="width: 40px; height: 40px;"></canvas>
<canvas id="example" width="32" height="32" style="width: 40px; height: 40px;"></canvas>
<div id="description"></div>
<div id="console"></div>
<script id="vshader" type="x-shader/x-vertex">
@ -149,14 +149,29 @@ function checkTexture(width, height, cubeMap) {
function fillLevel(level, width, height, color, opt_cubemap) {
var numPixels = width * height;
var pixels = new Uint8Array(numPixels * 4);
for (var jj = 0; jj < numPixels; ++jj) {
var pixels = null;
var largeDim = Math.max(width, height);
var smallDim = Math.min(width, height);
var pixelRow = new Uint8Array(largeDim * 4);
for (var jj = 0; jj < largeDim; ++jj) {
var off = jj * 4;
pixels[off + 0] = color[0];
pixels[off + 1] = color[1];
pixels[off + 2] = color[2];
pixels[off + 3] = color[3];
pixelRow[off + 0] = color[0];
pixelRow[off + 1] = color[1];
pixelRow[off + 2] = color[2];
pixelRow[off + 3] = color[3];
}
if (largeDim == numPixels) {
pixels = pixelRow;
} else {
var pixels = new Uint8Array(numPixels * 4);
for (var jj = 0; jj < smallDim; ++jj) {
var off = jj * largeDim * 4;
pixels.set(pixelRow, off);
}
}
var targets = opt_cubemap ? [
gl.TEXTURE_CUBE_MAP_POSITIVE_X,
gl.TEXTURE_CUBE_MAP_NEGATIVE_X,

View File

@ -519,18 +519,14 @@ function testConstructionWithOutOfRangeValues(type, name) {
}, "Construction of " + name + " with out-of-range offset");
}
function testConstructionWithNegativeOutOfRangeValues(type, name) {
try {
var buffer = new ArrayBuffer(-1);
testFailed("Construction of ArrayBuffer with negative size should throw exception");
} catch (e) {
testPassed("Construction of ArrayBuffer with negative size threw exception");
}
try {
var array = new type(-1);
testFailed("Construction of " + name + " with negative size should throw exception");
} catch (e) {
testPassed("Construction of " + name + " with negative size threw exception");
function testConstructionWithNegativeOutOfRangeValues(type, name, elementSizeInBytes) {
if (elementSizeInBytes > 1) {
try {
var array = new type(-1);
testFailed("Construction of " + name + " with negative size should throw exception");
} catch (e) {
testPassed("Construction of " + name + " with negative size threw exception");
}
}
shouldThrowIndexSizeErr(function() {
var buffer = new ArrayBuffer(4);
@ -895,7 +891,7 @@ function runTests() {
testCase.expectedValues);
testConstructionWithNullBuffer(type, name);
testConstructionWithOutOfRangeValues(type, name);
testConstructionWithNegativeOutOfRangeValues(type, name);
testConstructionWithNegativeOutOfRangeValues(type, name, testCase.elementSizeInBytes);
testConstructionWithUnalignedOffset(type, name, testCase.elementSizeInBytes);
testConstructionWithUnalignedLength(type, name, testCase.elementSizeInBytes);
testConstructionOfHugeArray(type, name, testCase.elementSizeInBytes);

View File

@ -95,6 +95,15 @@ locationArray0 = contextA.getUniformLocation(programS, "u_array[0]");
shouldGenerateGLError(contextA, contextA.NO_ERROR, "contextA.uniform1i(locationSx, 3)");
shouldBe("contextA.getUniform(programS, locationSx)", "3");
// getUniformLocation should return a different object everytime, should not cache and return the same object
debug("Testing that getUniformLocation returns a different object everytime");
locationSx = contextA.getUniformLocation(programS, "u_struct.x");
locationSx2 = contextA.getUniformLocation(programS, "u_struct.x");
shouldBeFalse("locationSx === locationSx2");
locationSx.foo = {};
locationSx2.foo = {};
shouldBeFalse("locationSx.foo === locationSx2.foo");
successfullyParsed = true;
</script>

View File

@ -1,22 +0,0 @@
# HG changeset patch
# Parent 587913950733649a7cbd184a195b08cbb86b2fed
diff --git a/content/canvas/test/webgl/conformance/more/00_test_list.txt b/content/canvas/test/webgl/conformance/more/00_test_list.txt
--- a/content/canvas/test/webgl/conformance/more/00_test_list.txt
+++ b/content/canvas/test/webgl/conformance/more/00_test_list.txt
@@ -1,12 +1,15 @@
conformance/constants.html
conformance/getContext.html
conformance/methods.html
-conformance/quickCheckAPI.html
+#this test causes whichever comes after to intermittently time out.
+#forcing a GC run doesn't solve this issue. Could be something about using a random amount of memory that
+#can be too high, causing e.g. swapping.
+#conformance/quickCheckAPI.html
conformance/webGLArrays.html
functions/bindBuffer.html
functions/bindBufferBadArgs.html
functions/bindFramebufferLeaveNonZero.html
functions/bufferData.html
functions/bufferDataBadArgs.html
functions/bufferSubData.html
functions/bufferSubDataBadArgs.html

View File

@ -1,6 +1,5 @@
# HG changeset patch
# Parent 95e5d92098ad52788348e609e261305d4b05b551
# Parent 9c1a90f789e3d43455cb18a9a911627c80c0d9ac
diff --git a/content/canvas/test/webgl/conformance/more/functions/readPixelsBadArgs.html b/content/canvas/test/webgl/conformance/more/functions/readPixelsBadArgs.html
--- a/content/canvas/test/webgl/conformance/more/functions/readPixelsBadArgs.html
+++ b/content/canvas/test/webgl/conformance/more/functions/readPixelsBadArgs.html

View File

@ -1,3 +1,4 @@
conformance/context/context-lost-restored.html
conformance/context/premultiplyalpha-test.html
conformance/glsl/misc/glsl-long-variable-names.html
conformance/glsl/misc/shader-with-256-character-identifier.frag.html

View File

@ -1,3 +1,4 @@
conformance/context/context-lost-restored.html
conformance/context/premultiplyalpha-test.html
conformance/glsl/misc/glsl-function-nodes.html
conformance/glsl/misc/glsl-long-variable-names.html

View File

@ -1,3 +1,4 @@
conformance/context/context-lost-restored.html
conformance/context/premultiplyalpha-test.html
conformance/glsl/functions/glsl-function-atan.html
conformance/glsl/functions/glsl-function-atan-xy.html
@ -11,3 +12,5 @@ conformance/glsl/misc/attrib-location-length-limits.html
conformance/glsl/misc/struct-nesting-under-maximum.html
conformance/glsl/misc/uniform-location-length-limits.html
conformance/renderbuffers/framebuffer-object-attachment.html
conformance/rendering/line-loop-tri-fan.html

View File

@ -1,16 +1,9 @@
# HG changeset patch
# Parent 2dbd71999fe8a8da476ab6cc97716f7b7c294fb8
# User Doug Sherk <dsherk@mozilla.com>
Bug 693703: added additional logging information for mochitests, incl. image reference differences r=bjacob
Added some code to print to dump output of WebGL mochitest failures. Also added
special code to handle incorrect reference images. It will now provide the user
with a way to compare the reference and actual drawings.
# Parent 4ed0bad4933ba69927ee5f75cf67093d3e99566a
diff --git a/content/canvas/test/webgl/conformance/glsl/misc/glsl-function-nodes.html b/content/canvas/test/webgl/conformance/glsl/misc/glsl-function-nodes.html
--- a/content/canvas/test/webgl/conformance/glsl/misc/glsl-function-nodes.html
+++ b/content/canvas/test/webgl/conformance/glsl/misc/glsl-function-nodes.html
@@ -115,17 +115,18 @@ function init()
@@ -117,17 +117,18 @@ function init()
var bufFunction = new Uint8Array(width * height * 4);
var bufMacro = new Uint8Array(width * height * 4);
@ -148,7 +141,7 @@ diff --git a/content/canvas/test/webgl/resources/js-test-pre.js b/content/canvas
+
+ testFailed(msg);
+
+ var data = 'REFTEST TEST-UNEXPECTED-FAIL | ' + msg + ' | image comparison (==)\n' +
+ var data = 'REFTEST TEST-DEBUG-INFO | ' + msg + ' | image comparison (==)\n' +
+ 'REFTEST IMAGE 1 (TEST): ' + testData + '\n' +
+ 'REFTEST IMAGE 2 (REFERENCE): ' + refData;
+ dump('FAIL: ' + data + '\n');

View File

@ -1,6 +1,5 @@
# HG changeset patch
# Parent 041265c6ac29c43856a8df4d4581cb6a04b95a68
# Parent bf9d7872738cdb7cf425e6dd060ae62882487e1a
diff --git a/content/canvas/test/webgl/conformance/extensions/oes-standard-derivatives.html b/content/canvas/test/webgl/conformance/extensions/oes-standard-derivatives.html
--- a/content/canvas/test/webgl/conformance/extensions/oes-standard-derivatives.html
+++ b/content/canvas/test/webgl/conformance/extensions/oes-standard-derivatives.html

View File

@ -1,5 +1,6 @@
# HG changeset patch
# Parent 0e44920c4e5e697f86e0a42b909c5a032d70a1a4
# Parent 41137626edf2a358f2be1b7ed3f83211230ab4f5
diff --git a/content/canvas/test/webgl/resources/webgl-test-harness.js b/content/canvas/test/webgl/resources/webgl-test-harness.js
--- a/content/canvas/test/webgl/resources/webgl-test-harness.js
+++ b/content/canvas/test/webgl/resources/webgl-test-harness.js