259 lines
10 KiB
JavaScript
259 lines
10 KiB
JavaScript
/*
|
|
Copyright (c) 2019 The Khronos Group Inc.
|
|
Use of this source code is governed by an MIT-style license that can be
|
|
found in the LICENSE.txt file.
|
|
*/
|
|
|
|
function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) {
|
|
var wtu = WebGLTestUtils;
|
|
var tiu = TexImageUtils;
|
|
var gl = null;
|
|
var successfullyParsed = false;
|
|
var imageData = null;
|
|
var blackColor = [0, 0, 0];
|
|
var originalPixels = (function() {
|
|
// (red|green|blue|cyan)(opaque|transparent)
|
|
var ro = [255, 0, 0, 255]; var rt = [255, 0, 0, 0];
|
|
var go = [0, 255, 0, 255]; var gt = [0, 255, 0, 0];
|
|
var bo = [0, 0, 255, 255]; var bt = [0, 0, 255, 0];
|
|
var co = [0, 255, 255, 255]; var ct = [0, 255, 255, 0];
|
|
return [ro, rt, go, gt,
|
|
ro, rt, go, gt,
|
|
bo, bt, co, ct,
|
|
bo, bt, co, ct];
|
|
})();
|
|
|
|
function init()
|
|
{
|
|
description('Verify texImage3D and texSubImage3D code paths taking ImageData (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')');
|
|
|
|
// Set the default context version while still allowing the webglVersion URL query string to override it.
|
|
wtu.setDefault3DContextVersion(defaultContextVersion);
|
|
gl = wtu.create3DContext("example");
|
|
|
|
if (!prologue(gl)) {
|
|
finishTest();
|
|
return;
|
|
}
|
|
|
|
gl.clearColor(0,0,0,1);
|
|
gl.clearDepth(1);
|
|
gl.disable(gl.BLEND);
|
|
|
|
var canvas2d = document.getElementById("texcanvas");
|
|
var context2d = canvas2d.getContext("2d");
|
|
imageData = context2d.createImageData(4, 4);
|
|
var data = imageData.data;
|
|
for (var i = 0; i < originalPixels.length; i++) {
|
|
data.set(originalPixels[i], 4 * i);
|
|
}
|
|
|
|
runTest();
|
|
}
|
|
|
|
function runOneIteration(useTexSubImage3D, flipY, premultiplyAlpha, bindingTarget,
|
|
depth, sourceSubRectangle, rTexCoord, program)
|
|
{
|
|
var expected = simulate(flipY, premultiplyAlpha, depth, sourceSubRectangle, rTexCoord);
|
|
var sourceSubRectangleString = '';
|
|
if (sourceSubRectangle) {
|
|
sourceSubRectangleString = ', sourceSubRectangle=' + sourceSubRectangle;
|
|
sourceSubRectangleString += ', rTexCoord=' + rTexCoord;
|
|
}
|
|
debug('');
|
|
debug('Testing ' + (useTexSubImage3D ? 'texSubImage3D' : 'texImage3D') +
|
|
' with flipY=' + flipY + ', premultiplyAlpha=' + premultiplyAlpha +
|
|
', bindingTarget=' + (bindingTarget == gl.TEXTURE_3D ? 'TEXTURE_3D' : 'TEXTURE_2D_ARRAY') +
|
|
sourceSubRectangleString);
|
|
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
// Enable writes to the RGBA channels
|
|
gl.colorMask(1, 1, 1, 0);
|
|
var texture = gl.createTexture();
|
|
// Bind the texture to texture unit 0
|
|
gl.bindTexture(bindingTarget, texture);
|
|
// Set up texture parameters
|
|
gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
|
gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE);
|
|
// Set up pixel store parameters
|
|
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
|
|
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha);
|
|
gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);
|
|
var uploadWidth = imageData.width;
|
|
var uploadHeight = imageData.height;
|
|
if (sourceSubRectangle) {
|
|
gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, sourceSubRectangle[0]);
|
|
gl.pixelStorei(gl.UNPACK_SKIP_ROWS, sourceSubRectangle[1]);
|
|
uploadWidth = sourceSubRectangle[2];
|
|
uploadHeight = sourceSubRectangle[3];
|
|
}
|
|
// Upload the image into the texture
|
|
if (useTexSubImage3D) {
|
|
// Initialize the texture to black first
|
|
gl.texImage3D(bindingTarget, 0, gl[internalFormat], uploadWidth, uploadHeight, depth, 0,
|
|
gl[pixelFormat], gl[pixelType], null);
|
|
gl.texSubImage3D(bindingTarget, 0, 0, 0, 0, uploadWidth, uploadHeight, depth,
|
|
gl[pixelFormat], gl[pixelType], imageData);
|
|
} else {
|
|
gl.texImage3D(bindingTarget, 0, gl[internalFormat], uploadWidth, uploadHeight, depth, 0,
|
|
gl[pixelFormat], gl[pixelType], imageData);
|
|
}
|
|
gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0);
|
|
gl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0);
|
|
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from texture upload");
|
|
|
|
var tl = expected[0][0];
|
|
var tr = expected[0][1];
|
|
var bl = expected[1][0];
|
|
var br = expected[1][1];
|
|
|
|
var rCoordLocation = gl.getUniformLocation(program, 'uRCoord');
|
|
if (!rCoordLocation) {
|
|
testFailed("Shader incorrectly set up; couldn't find uRCoord uniform");
|
|
return;
|
|
}
|
|
gl.uniform1f(rCoordLocation, rTexCoord);
|
|
// Draw the triangles
|
|
wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]);
|
|
|
|
var width = gl.canvas.width;
|
|
var halfWidth = Math.floor(width / 2);
|
|
var height = gl.canvas.height;
|
|
var halfHeight = Math.floor(height / 2);
|
|
|
|
var top = 0;
|
|
var bottom = height - halfHeight;
|
|
var left = 0;
|
|
var right = width - halfWidth;
|
|
|
|
debug("Checking pixel values");
|
|
debug("Expecting: " + expected);
|
|
var expectedH = expected.length;
|
|
var expectedW = expected[0].length;
|
|
var texelH = Math.floor(gl.canvas.height / expectedH);
|
|
var texelW = Math.floor(gl.canvas.width / expectedW);
|
|
// For each entry of the expected[][] array, check the appropriate
|
|
// canvas rectangle for correctness.
|
|
for (var row = 0; row < expectedH; row++) {
|
|
var y = row * texelH;
|
|
for (var col = 0; col < expectedW; col++) {
|
|
var x = col * texelW;
|
|
var val = expected[row][col];
|
|
wtu.checkCanvasRect(gl, x, y, texelW, texelH, val, "should be " + val);
|
|
}
|
|
}
|
|
}
|
|
|
|
function runTest()
|
|
{
|
|
var program = tiu.setupTexturedQuadWith3D(gl, internalFormat);
|
|
runTestOnBindingTarget(gl.TEXTURE_3D, program);
|
|
program = tiu.setupTexturedQuadWith2DArray(gl, internalFormat);
|
|
runTestOnBindingTarget(gl.TEXTURE_2D_ARRAY, program);
|
|
|
|
debug("");
|
|
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
|
|
finishTest();
|
|
}
|
|
|
|
function simulate(flipY, premultiplyAlpha, depth, sourceSubRectangle, rTexCoord) {
|
|
var ro = [255, 0, 0]; var rt = premultiplyAlpha ? [0, 0, 0] : [255, 0, 0];
|
|
var go = [0, 255, 0]; var gt = premultiplyAlpha ? [0, 0, 0] : [0, 255, 0];
|
|
var bo = [0, 0, 255]; var bt = premultiplyAlpha ? [0, 0, 0] : [0, 0, 255];
|
|
var co = [0, 255, 255]; var ct = premultiplyAlpha ? [0, 0, 0] : [0, 255, 255];
|
|
var expected = [[ro, rt, go, gt],
|
|
[ro, rt, go, gt],
|
|
[bo, bt, co, ct],
|
|
[bo, bt, co, ct]];
|
|
switch (gl[pixelFormat]) {
|
|
case gl.RED:
|
|
case gl.RED_INTEGER:
|
|
for (var row = 0; row < 4; row++) {
|
|
for (var col = 0; col < 4; col++) {
|
|
expected[row][col][1] = 0; // zero the green channel
|
|
}
|
|
}
|
|
// fall-through
|
|
case gl.RG:
|
|
case gl.RG_INTEGER:
|
|
for (var row = 0; row < 4; row++) {
|
|
for (var col = 0; col < 4; col++) {
|
|
expected[row][col][2] = 0; // zero the blue channel
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (flipY) {
|
|
expected.reverse();
|
|
}
|
|
|
|
if (sourceSubRectangle) {
|
|
let expected2 = [];
|
|
for (var row = 0; row < sourceSubRectangle[3]; row++) {
|
|
expected2[row] = [];
|
|
for (var col = 0; col < sourceSubRectangle[2]; col++) {
|
|
expected2[row][col] =
|
|
expected[sourceSubRectangle[1] + row + rTexCoord * sourceSubRectangle[3]][sourceSubRectangle[0] + col];
|
|
}
|
|
}
|
|
expected = expected2;
|
|
}
|
|
|
|
return expected;
|
|
}
|
|
|
|
function runTestOnBindingTarget(bindingTarget, program) {
|
|
var rects = [
|
|
undefined,
|
|
[0, 0, 2, 2],
|
|
[2, 0, 2, 2],
|
|
];
|
|
var dbg = false; // Set to true for debug output images
|
|
if (dbg) {
|
|
(function() {
|
|
debug("");
|
|
debug("Original ImageData (transparent pixels appear black):");
|
|
var cvs = document.createElement("canvas");
|
|
cvs.width = 4;
|
|
cvs.height = 4;
|
|
cvs.style.width = "32px";
|
|
cvs.style.height = "32px";
|
|
cvs.style.imageRendering = "pixelated";
|
|
cvs.style.background = "#000";
|
|
var ctx = cvs.getContext("2d");
|
|
ctx.putImageData(imageData, 0, 0);
|
|
var output = document.getElementById("console");
|
|
output.appendChild(cvs);
|
|
})();
|
|
}
|
|
for (const sub of [false, true]) {
|
|
for (const flipY of [false, true]) {
|
|
for (const premul of [false, true]) {
|
|
for (let irect = 0; irect < rects.length; irect++) {
|
|
var rect = rects[irect];
|
|
let depth = rect ? 2 : 1;
|
|
for (let rTexCoord = 0; rTexCoord < depth; rTexCoord++) {
|
|
// TODO: add tests for UNPACK_IMAGE_HEIGHT.
|
|
runOneIteration(sub, flipY, premul, bindingTarget,
|
|
depth, rect, rTexCoord, program);
|
|
if (dbg) {
|
|
debug("Actual:");
|
|
var img = document.createElement("img");
|
|
img.src = gl.canvas.toDataURL("image/png");
|
|
var output = document.getElementById("console");
|
|
output.appendChild(img);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return init;
|
|
}
|