mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-31 11:37:30 +09:00
392 lines
14 KiB
HTML
392 lines
14 KiB
HTML
|
|
<!--
|
||
|
|
|
||
|
|
/*
|
||
|
|
** Copyright (c) 2013 The Khronos Group Inc.
|
||
|
|
**
|
||
|
|
** Permission is hereby granted, free of charge, to any person obtaining a
|
||
|
|
** copy of this software and/or associated documentation files (the
|
||
|
|
** "Materials"), to deal in the Materials without restriction, including
|
||
|
|
** without limitation the rights to use, copy, modify, merge, publish,
|
||
|
|
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||
|
|
** permit persons to whom the Materials are furnished to do so, subject to
|
||
|
|
** the following conditions:
|
||
|
|
**
|
||
|
|
** The above copyright notice and this permission notice shall be included
|
||
|
|
** in all copies or substantial portions of the Materials.
|
||
|
|
**
|
||
|
|
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||
|
|
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||
|
|
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||
|
|
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||
|
|
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||
|
|
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||
|
|
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||
|
|
*/
|
||
|
|
|
||
|
|
-->
|
||
|
|
|
||
|
|
<!DOCTYPE html>
|
||
|
|
<html>
|
||
|
|
<head>
|
||
|
|
<meta charset="utf-8">
|
||
|
|
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
|
||
|
|
<script src="../../js/js-test-pre.js"></script>
|
||
|
|
<script src="../../js/webgl-test-utils.js"></script>
|
||
|
|
<title>WebGL WEBGL_compressed_texture_pvrtc Conformance Tests</title>
|
||
|
|
<style>
|
||
|
|
img {
|
||
|
|
border: 1px solid black;
|
||
|
|
margin-right: 1em;
|
||
|
|
}
|
||
|
|
.testimages {
|
||
|
|
}
|
||
|
|
|
||
|
|
.testimages br {
|
||
|
|
clear: both;
|
||
|
|
}
|
||
|
|
|
||
|
|
.testimages > div {
|
||
|
|
float: left;
|
||
|
|
margin: 1em;
|
||
|
|
}
|
||
|
|
</style>
|
||
|
|
</head>
|
||
|
|
<body>
|
||
|
|
<div id="description"></div>
|
||
|
|
<canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas>
|
||
|
|
<div id="console"></div>
|
||
|
|
<script>
|
||
|
|
"use strict";
|
||
|
|
description("This test verifies the functionality of the WEBGL_compressed_texture_pvrtc extension, if it is available.");
|
||
|
|
|
||
|
|
debug("");
|
||
|
|
|
||
|
|
var pvrtc_4x4_2bpp = new Uint8Array([
|
||
|
|
0x77, 0x22, 0x77, 0x22, 0xbb, 0x2b, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
|
|
]);
|
||
|
|
|
||
|
|
var pvrtc_4x4_4bpp = new Uint8Array([
|
||
|
|
0x1b, 0x1b, 0x1b, 0x1b, 0xba, 0x2b, 0x00, 0x80, 0x1b, 0x1b, 0x1b, 0x1b, 0xba, 0x2b, 0x00, 0x80,
|
||
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
|
|
]);
|
||
|
|
|
||
|
|
var pvrtc_4x4_rgba_decoded = new Uint8Array([
|
||
|
|
0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x46, 0xb8, 0x76, 0x76, 0x71, 0x8a, 0xbd, 0xbd, 0xba, 0x44,
|
||
|
|
0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x43, 0xb8, 0x76, 0x76, 0x71, 0x8a, 0xbd, 0xbd, 0xb5, 0x44,
|
||
|
|
0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x43, 0xb8, 0x76, 0x76, 0x71, 0x8a, 0xbd, 0xbd, 0xb5, 0x44,
|
||
|
|
0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x46, 0xb8, 0x76, 0x76, 0x71, 0x8a, 0xbd, 0xbd, 0xb7, 0x44,
|
||
|
|
]);
|
||
|
|
|
||
|
|
var pvrtc_4x4_rgb_decoded = new Uint8Array([
|
||
|
|
0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x46, 0xff, 0x76, 0x76, 0x71, 0xff, 0xbd, 0xbd, 0xba, 0xff,
|
||
|
|
0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x43, 0xff, 0x76, 0x76, 0x71, 0xff, 0xbd, 0xbd, 0xb5, 0xff,
|
||
|
|
0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x43, 0xff, 0x76, 0x76, 0x71, 0xff, 0xbd, 0xbd, 0xb5, 0xff,
|
||
|
|
0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x46, 0xff, 0x76, 0x76, 0x71, 0xff, 0xbd, 0xbd, 0xb7, 0xff,
|
||
|
|
]);
|
||
|
|
|
||
|
|
var wtu = WebGLTestUtils;
|
||
|
|
var contextVersion = wtu.getDefault3DContextVersion();
|
||
|
|
var canvas = document.getElementById("canvas");
|
||
|
|
var gl = wtu.create3DContext(canvas, {antialias: false});
|
||
|
|
var program = wtu.setupTexturedQuad(gl);
|
||
|
|
var ext = null;
|
||
|
|
var vao = null;
|
||
|
|
var validFormats = {
|
||
|
|
COMPRESSED_RGB_PVRTC_4BPPV1_IMG : 0x8C00,
|
||
|
|
COMPRESSED_RGB_PVRTC_2BPPV1_IMG : 0x8C01,
|
||
|
|
COMPRESSED_RGBA_PVRTC_4BPPV1_IMG : 0x8C02,
|
||
|
|
COMPRESSED_RGBA_PVRTC_2BPPV1_IMG : 0x8C03,
|
||
|
|
};
|
||
|
|
var name;
|
||
|
|
var supportedFormats;
|
||
|
|
|
||
|
|
if (!gl) {
|
||
|
|
testFailed("WebGL context does not exist");
|
||
|
|
} else {
|
||
|
|
testPassed("WebGL context exists");
|
||
|
|
|
||
|
|
// Run tests with extension disabled
|
||
|
|
runTestDisabled();
|
||
|
|
|
||
|
|
// Query the extension and store globally so shouldBe can access it
|
||
|
|
ext = wtu.getExtensionWithKnownPrefixes(gl, "WEBGL_compressed_texture_pvrtc");
|
||
|
|
if (!ext) {
|
||
|
|
testPassed("No WEBGL_compressed_texture_pvrtc support -- this is legal");
|
||
|
|
runSupportedTest(false);
|
||
|
|
} else {
|
||
|
|
testPassed("Successfully enabled WEBGL_compressed_texture_pvrtc extension");
|
||
|
|
|
||
|
|
runSupportedTest(true);
|
||
|
|
runTestExtension();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function runSupportedTest(extensionEnabled) {
|
||
|
|
var name = wtu.getSupportedExtensionWithKnownPrefixes(gl, "WEBGL_compressed_texture_pvrtc");
|
||
|
|
if (name !== undefined) {
|
||
|
|
if (extensionEnabled) {
|
||
|
|
testPassed("WEBGL_compressed_texture_pvrtc listed as supported and getExtension succeeded");
|
||
|
|
} else {
|
||
|
|
testFailed("WEBGL_compressed_texture_pvrtc listed as supported but getExtension failed");
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
if (extensionEnabled) {
|
||
|
|
testFailed("WEBGL_compressed_texture_pvrtc not listed as supported but getExtension succeeded");
|
||
|
|
} else {
|
||
|
|
testPassed("WEBGL_compressed_texture_pvrtc not listed as supported and getExtension failed -- this is legal");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
function runTestDisabled() {
|
||
|
|
debug("Testing binding enum with extension disabled");
|
||
|
|
|
||
|
|
supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
|
||
|
|
shouldBe("supportedFormats", "[]");
|
||
|
|
}
|
||
|
|
|
||
|
|
function formatExists(format, supportedFormats) {
|
||
|
|
for (var ii = 0; ii < supportedFormats.length; ++ii) {
|
||
|
|
if (format == supportedFormats[ii]) {
|
||
|
|
testPassed("supported format " + formatToString(format) + " is exists");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
testFailed("supported format " + formatToString(format) + " does not exist");
|
||
|
|
}
|
||
|
|
|
||
|
|
function formatToString(format) {
|
||
|
|
for (var p in ext) {
|
||
|
|
if (ext[p] == format) {
|
||
|
|
return p;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return "0x" + format.toString(16);
|
||
|
|
}
|
||
|
|
|
||
|
|
function runTestExtension() {
|
||
|
|
debug("Testing WEBGL_compressed_texture_pvrtc");
|
||
|
|
|
||
|
|
// check that all format enums exist.
|
||
|
|
for (name in validFormats) {
|
||
|
|
var expected = "0x" + validFormats[name].toString(16);
|
||
|
|
var actual = "ext['" + name + "']";
|
||
|
|
shouldBe(actual, expected);
|
||
|
|
}
|
||
|
|
|
||
|
|
supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
|
||
|
|
// There should be exactly 4 formats for both WebGL 1.0 and WebGL 2.0.
|
||
|
|
shouldBe("supportedFormats.length", "4");
|
||
|
|
|
||
|
|
// check that all 4 formats exist
|
||
|
|
for (var name in validFormats.length) {
|
||
|
|
formatExists(validFormats[name], supportedFormats);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Test each format
|
||
|
|
testPVRTC_RGBA_2BPP();
|
||
|
|
testPVRTC_RGB_2BPP();
|
||
|
|
testPVRTC_RGBA_4BPP();
|
||
|
|
testPVRTC_RGB_4BPP();
|
||
|
|
}
|
||
|
|
|
||
|
|
function testPVRTC_RGBA_2BPP() {
|
||
|
|
var tests = [
|
||
|
|
{ width: 4,
|
||
|
|
height: 4,
|
||
|
|
channels: 4,
|
||
|
|
data: pvrtc_4x4_2bpp,
|
||
|
|
raw: pvrtc_4x4_rgba_decoded,
|
||
|
|
format: ext.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
|
||
|
|
}
|
||
|
|
];
|
||
|
|
testPVRTCTextures(tests);
|
||
|
|
}
|
||
|
|
|
||
|
|
function testPVRTC_RGB_2BPP() {
|
||
|
|
var tests = [
|
||
|
|
{ width: 4,
|
||
|
|
height: 4,
|
||
|
|
channels: 4,
|
||
|
|
data: pvrtc_4x4_2bpp,
|
||
|
|
raw: pvrtc_4x4_rgb_decoded,
|
||
|
|
format: ext.COMPRESSED_RGB_PVRTC_2BPPV1_IMG
|
||
|
|
}
|
||
|
|
];
|
||
|
|
testPVRTCTextures(tests);
|
||
|
|
}
|
||
|
|
|
||
|
|
function testPVRTC_RGBA_4BPP() {
|
||
|
|
var tests = [
|
||
|
|
{ width: 4,
|
||
|
|
height: 4,
|
||
|
|
channels: 4,
|
||
|
|
data: pvrtc_4x4_4bpp,
|
||
|
|
raw: pvrtc_4x4_rgba_decoded,
|
||
|
|
format: ext.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
|
||
|
|
}
|
||
|
|
];
|
||
|
|
testPVRTCTextures(tests);
|
||
|
|
}
|
||
|
|
|
||
|
|
function testPVRTC_RGB_4BPP() {
|
||
|
|
var tests = [
|
||
|
|
{ width: 4,
|
||
|
|
height: 4,
|
||
|
|
channels: 4,
|
||
|
|
data: pvrtc_4x4_4bpp,
|
||
|
|
raw: pvrtc_4x4_rgb_decoded,
|
||
|
|
format: ext.COMPRESSED_RGB_PVRTC_4BPPV1_IMG
|
||
|
|
}
|
||
|
|
];
|
||
|
|
testPVRTCTextures(tests);
|
||
|
|
}
|
||
|
|
|
||
|
|
function testPVRTCTextures(tests) {
|
||
|
|
debug("<hr/>");
|
||
|
|
for (var ii = 0; ii < tests.length; ++ii) {
|
||
|
|
testPVRTCTexture(tests[ii]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function testPVRTCTexture(test) {
|
||
|
|
var data = new Uint8Array(test.data);
|
||
|
|
var width = test.width;
|
||
|
|
var height = test.height;
|
||
|
|
var format = test.format;
|
||
|
|
var uncompressedData = test.raw;
|
||
|
|
|
||
|
|
canvas.width = width;
|
||
|
|
canvas.height = height;
|
||
|
|
gl.viewport(0, 0, width, height);
|
||
|
|
debug("testing " + formatToString(format) + " " + width + "x" + height);
|
||
|
|
|
||
|
|
var tex = gl.createTexture();
|
||
|
|
gl.bindTexture(gl.TEXTURE_2D, tex);
|
||
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
||
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||
|
|
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, data);
|
||
|
|
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture");
|
||
|
|
gl.generateMipmap(gl.TEXTURE_2D);
|
||
|
|
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "trying to generate mipmaps from compressed texture");
|
||
|
|
wtu.drawQuad(gl);
|
||
|
|
compareRect(width, height, test.channels, width, height, uncompressedData, data, format, undefined, "NEAREST");
|
||
|
|
// Test again with linear filtering.
|
||
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
||
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
||
|
|
wtu.clearAndDrawUnitQuad(gl);
|
||
|
|
compareRect(width, height, test.channels, width, height, uncompressedData, data, format, undefined, "LINEAR");
|
||
|
|
|
||
|
|
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 1, data);
|
||
|
|
wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "non 0 border");
|
||
|
|
|
||
|
|
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 1, height, 0, data);
|
||
|
|
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
|
||
|
|
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 2, height, 0, data);
|
||
|
|
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
|
||
|
|
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 1, 0, data);
|
||
|
|
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
|
||
|
|
gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 2, 0, data);
|
||
|
|
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
|
||
|
|
|
||
|
|
gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, format, data);
|
||
|
|
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "compressedTexSubImage2D allowed for reloading of complete textures");
|
||
|
|
|
||
|
|
gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width - 2, height, format, data);
|
||
|
|
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "compressedTexSubImage2D not allowed for partial texture updates");
|
||
|
|
gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height - 2, format, data);
|
||
|
|
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "compressedTexSubImage2D not allowed for partial texture updates");
|
||
|
|
gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 2, 0, width - 2, height, format, data);
|
||
|
|
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "compressedTexSubImage2D not allowed for partial texture updates");
|
||
|
|
gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 2, width, height - 2, format, data);
|
||
|
|
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "compressedTexSubImage2D not allowed for partial texture updates");
|
||
|
|
}
|
||
|
|
|
||
|
|
function insertImg(element, caption, img) {
|
||
|
|
var div = document.createElement("div");
|
||
|
|
div.appendChild(img);
|
||
|
|
var label = document.createElement("div");
|
||
|
|
label.appendChild(document.createTextNode(caption));
|
||
|
|
div.appendChild(label);
|
||
|
|
element.appendChild(div);
|
||
|
|
}
|
||
|
|
|
||
|
|
function makeImage(imageWidth, imageHeight, dataWidth, data, alpha) {
|
||
|
|
var scale = 8;
|
||
|
|
var c = document.createElement("canvas");
|
||
|
|
c.width = imageWidth * scale;
|
||
|
|
c.height = imageHeight * scale;
|
||
|
|
var ctx = c.getContext("2d");
|
||
|
|
for (var yy = 0; yy < imageHeight; ++yy) {
|
||
|
|
for (var xx = 0; xx < imageWidth; ++xx) {
|
||
|
|
var offset = (yy * dataWidth + xx) * 4;
|
||
|
|
ctx.fillStyle = "rgba(" +
|
||
|
|
data[offset + 0] + "," +
|
||
|
|
data[offset + 1] + "," +
|
||
|
|
data[offset + 2] + "," +
|
||
|
|
(alpha ? data[offset + 3] / 255 : 1) + ")";
|
||
|
|
ctx.fillRect(xx * scale, yy * scale, scale, scale);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return wtu.makeImageFromCanvas(c);
|
||
|
|
}
|
||
|
|
function compareRect(
|
||
|
|
actualWidth, actualHeight, actualChannels,
|
||
|
|
dataWidth, dataHeight, expectedData,
|
||
|
|
testData, testFormat, tolerance, filteringMode) {
|
||
|
|
if(typeof(tolerance) == 'undefined') { tolerance = 5; }
|
||
|
|
var actual = new Uint8Array(actualWidth * actualHeight * 4);
|
||
|
|
gl.readPixels(
|
||
|
|
0, 0, actualWidth, actualHeight, gl.RGBA, gl.UNSIGNED_BYTE, actual);
|
||
|
|
|
||
|
|
var div = document.createElement("div");
|
||
|
|
div.className = "testimages";
|
||
|
|
insertImg(div, "expected", makeImage(
|
||
|
|
actualWidth, actualHeight, dataWidth, expectedData,
|
||
|
|
actualChannels == 4));
|
||
|
|
insertImg(div, "actual", makeImage(
|
||
|
|
actualWidth, actualHeight, actualWidth, actual,
|
||
|
|
actualChannels == 4));
|
||
|
|
div.appendChild(document.createElement('br'));
|
||
|
|
document.getElementById("console").appendChild(div);
|
||
|
|
|
||
|
|
var failed = false;
|
||
|
|
for (var yy = 0; yy < actualHeight; ++yy) {
|
||
|
|
for (var xx = 0; xx < actualWidth; ++xx) {
|
||
|
|
var actualOffset = (yy * actualWidth + xx) * 4;
|
||
|
|
var expectedOffset = (yy * dataWidth + xx) * 4;
|
||
|
|
var expected = [
|
||
|
|
expectedData[expectedOffset + 0],
|
||
|
|
expectedData[expectedOffset + 1],
|
||
|
|
expectedData[expectedOffset + 2],
|
||
|
|
(actualChannels == 3 ? 255 : expectedData[expectedOffset + 3])
|
||
|
|
];
|
||
|
|
for (var jj = 0; jj < 4; ++jj) {
|
||
|
|
if (Math.abs(actual[actualOffset + jj] - expected[jj]) > tolerance) {
|
||
|
|
failed = true;
|
||
|
|
var was = actual[actualOffset + 0].toString();
|
||
|
|
for (var j = 1; j < 4; ++j) {
|
||
|
|
was += "," + actual[actualOffset + j];
|
||
|
|
}
|
||
|
|
testFailed('at (' + xx + ', ' + yy +
|
||
|
|
') expected: ' + expected + ' was ' + was);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (!failed) {
|
||
|
|
testPassed("texture rendered correctly with " + filteringMode + " filtering");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
debug("");
|
||
|
|
var successfullyParsed = true;
|
||
|
|
</script>
|
||
|
|
<script src="../../js/js-test-post.js"></script>
|
||
|
|
|
||
|
|
</body>
|
||
|
|
</html>
|