diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ext-color-buffer-float.html | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ext-color-buffer-float.html')
-rw-r--r-- | dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ext-color-buffer-float.html | 508 |
1 files changed, 508 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ext-color-buffer-float.html b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ext-color-buffer-float.html new file mode 100644 index 0000000000..b57a6ca10d --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ext-color-buffer-float.html @@ -0,0 +1,508 @@ +<!-- +Copyright (c) 2019 The Khronos Group Inc. +Use of this source code is governed by an MIT-style license that can be +found in the LICENSE.txt file. +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL EXT_color_buffer_float Conformance Tests</title> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"></script> +</head> +<body> +<div id="description"></div> +<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas> +<div id="console"></div> +<!-- Shaders for testing floating-point textures --> +<script id="testFragmentShader" type="x-shader/x-fragment"> +precision mediump float; +uniform sampler2D tex; +uniform vec4 subtractor; +varying vec2 texCoord; +void main() +{ + vec4 color = texture2D(tex, texCoord); + if (abs(color.r - subtractor.r) + + abs(color.g - subtractor.g) + + abs(color.b - subtractor.b) + + abs(color.a - subtractor.a) < 16.0) { + gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); + } else { + gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); + } +} +</script> +<!-- Shaders for testing floating-point render targets --> +<script id="floatingPointFragmentShader" type="x-shader/x-fragment"> +void main() +{ + gl_FragColor = vec4(1000.0, 1000.0, 1000.0, 1000.0); +} +</script> +<script> +"use strict"; + +function allocateTexture() +{ + var texture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texture parameter setup should succeed"); + return texture; +} + +function checkRenderingResults() +{ + wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green"); +} + +function arrayToString(arr, size) { + var mySize; + if (!size) + mySize = arr.length; + else + mySize = size; + var out = "["; + for (var ii = 0; ii < mySize; ++ii) { + if (ii > 0) { + out += ", "; + } + out += arr[ii]; + } + return out + "]"; +} + +function runReadbackTest(testProgram, subtractor) +{ + // Verify floating point readback + debug("Checking readback of floating-point values"); + var buf = new Float32Array(4); + gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.FLOAT , buf); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "readPixels from floating-point framebuffer should succeed"); + var ok = true; + var tolerance = 8.0; // TODO: factor this out from both this test and the subtractor shader above. + for (var ii = 0; ii < buf.length; ++ii) { + if (Math.abs(buf[ii] - subtractor[ii]) > tolerance) { + ok = false; + break; + } + } + if (ok) { + testPassed("readPixels of float-type data from floating-point framebuffer succeeded"); + } else { + testFailed("readPixels of float-type data from floating-point framebuffer failed: expected " + + arrayToString(subtractor, 4) + ", got " + arrayToString(buf)); + } +} + +function runFloatTextureRenderTargetTest(enabled, internalFormat, format, testProgram, numberOfChannels, subtractor, texSubImageCover) +{ + var formatString = wtu.glEnumToString(gl, internalFormat); + debug(""); + debug("testing floating-point " + formatString + " texture render target" + (texSubImageCover > 0 ? " after calling texSubImage" : "")); + + var texture = allocateTexture(); + var width = 2; + var height = 2; + gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, width, height, 0, format, gl.FLOAT, null); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "floating-point texture allocation should succeed"); + + // Try to use this texture as a render target. + var fbo = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); + gl.bindTexture(gl.TEXTURE_2D, null); + + var completeStatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER); + if (!enabled) { + if (completeStatus == gl.FRAMEBUFFER_COMPLETE && !enabled) + testFailed("floating-point " + formatString + " render target should not be supported without enabling EXT_color_buffer_float"); + else + testPassed("floating-point " + formatString + " render target should not be supported without enabling EXT_color_buffer_float"); + return; + } + + if (completeStatus != gl.FRAMEBUFFER_COMPLETE) { + testFailed("floating-point " + formatString + " render target not supported"); + return; + } + + if (texSubImageCover > 0) { + // Ensure that replacing the whole texture or a part of it with texSubImage2D doesn't affect renderability + gl.bindTexture(gl.TEXTURE_2D, texture); + var data = new Float32Array(width * height * numberOfChannels * texSubImageCover); + gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height * texSubImageCover, format, gl.FLOAT, data); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage2D should succeed if EXT_color_buffer_float is enabled"); + gl.bindTexture(gl.TEXTURE_2D, null); + if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) { + testFailed("render target support changed after calling texSubImage2D"); + return; + } + } + + var renderProgram = + wtu.setupProgram(gl, + [wtu.simpleVertexShader, "floatingPointFragmentShader"], + ['vPosition'], + [0]); + wtu.clearAndDrawUnitQuad(gl); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "rendering to floating-point texture should succeed"); + + // Now sample from the floating-point texture and verify we got the correct values. + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.useProgram(testProgram); + gl.uniform1i(gl.getUniformLocation(testProgram, "tex"), 0); + gl.uniform4fv(gl.getUniformLocation(testProgram, "subtractor"), subtractor); + wtu.clearAndDrawUnitQuad(gl); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "rendering from floating-point texture should succeed"); + checkRenderingResults(); + + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); + runReadbackTest(testProgram, subtractor); +} + +function runFloatRenderbufferRenderTargetTest(enabled, internalFormat, testProgram, numberOfChannels, subtractor) +{ + var formatString = wtu.glEnumToString(gl, internalFormat); + var samples = [0]; + if (enabled) { + samples = Array.prototype.slice.call(gl.getInternalformatParameter(gl.RENDERBUFFER, internalFormat, gl.SAMPLES)); + samples.push(0); + } + for (var ndx = 0; ndx < samples.length; ++ndx) { + debug(""); + debug("testing floating-point " + formatString + " renderbuffer render target with number of samples " + samples[ndx]); + + var colorbuffer = gl.createRenderbuffer(); + var width = 2; + var height = 2; + gl.bindRenderbuffer(gl.RENDERBUFFER, colorbuffer); + if (samples[ndx] == 0) + gl.renderbufferStorage(gl.RENDERBUFFER, internalFormat, width, height); + else + gl.renderbufferStorageMultisample(gl.RENDERBUFFER, samples[ndx], internalFormat, width, height); + if (!enabled) { + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "floating-point renderbuffer allocation should fail if EXT_color_buffer_float is not enabled"); + return; + } else { + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "floating-point renderbuffer allocation should succeed if EXT_color_buffer_float is enabled"); + } + + // Try to use this renderbuffer as a render target. + var fbo = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorbuffer); + + var completeStatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER); + if (completeStatus != gl.FRAMEBUFFER_COMPLETE) { + testFailed("floating-point " + formatString + " render target not supported"); + return; + } + var resolveColorRbo = null; + var resolveFbo = null; + if (samples[ndx] > 0) { + resolveColorRbo = gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, resolveColorRbo); + gl.renderbufferStorage(gl.RENDERBUFFER, internalFormat, width, height); + resolveFbo = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, resolveFbo); + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, resolveColorRbo); + completeStatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER); + if (completeStatus != gl.FRAMEBUFFER_COMPLETE) { + testFailed("Failed to create resolve framebuffer"); + return; + } + } + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); + gl.clearColor(1000.0, 1000.0, 1000.0, 1000.0); + gl.clear(gl.COLOR_BUFFER_BIT); + + if (samples[ndx] > 0) { + gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, resolveFbo); + gl.blitFramebuffer(0, 0, width, height, 0, 0, width, height, gl.COLOR_BUFFER_BIT, gl.NEAREST); + gl.bindFramebuffer(gl.READ_FRAMEBUFFER, resolveFbo); + } + runReadbackTest(testProgram, subtractor); + } +} + +function runRGB16FNegativeTest() +{ + debug(""); + debug("testing RGB16F isn't color renderable"); + + var texture = allocateTexture(); + var width = 2; + var height = 2; + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB16F, width, height, 0, gl.RGB, gl.FLOAT, null); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "RGB16F texture allocation should succeed"); + + // Try to use this texture as a render target. + var fbo = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); + gl.bindTexture(gl.TEXTURE_2D, null); + + var completeStatus = gl.checkFramebufferStatus(gl.FRAMEBUFFER); + if (completeStatus == gl.FRAMEBUFFER_COMPLETE) + testFailed("RGB16F render target should not be supported with or without enabling EXT_color_buffer_float"); + else + testPassed("RGB16F render target should not be supported with or without enabling EXT_color_buffer_float"); + gl.deleteTexture(texture); + + var colorbuffer = gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, colorbuffer); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGB16F, width, height); + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "RGB16F renderbuffer allocation should fail with or without enabling EXT_color_buffer_float"); + gl.bindRenderbuffer(gl.RENDERBUFFER, null); + gl.deleteRenderbuffer(colorbuffer); + + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + gl.deleteFramebuffer(fbo); +} + +function runUniqueObjectTest() +{ + debug(""); + debug("Testing that getExtension() returns the same object each time"); + gl.getExtension("EXT_color_buffer_float").myProperty = 2; + webglHarnessCollectGarbage(); + shouldBe('gl.getExtension("EXT_color_buffer_float").myProperty', '2'); +} + +function runInternalFormatQueryTest() +{ + debug(""); + debug("testing the internal format query"); + + var maxSamples = gl.getParameter(gl.MAX_SAMPLES); + const formats = [gl.RGBA16F, gl.R32F, gl.RG32F, gl.RGBA32F, gl.R16F, gl.RG16F, gl.R11F_G11F_B10F]; + var firstMultiOnlyFormat = 4; + for (var fmt = 0; fmt < formats.length; ++fmt) { + var samples = gl.getInternalformatParameter(gl.RENDERBUFFER, formats[fmt], gl.SAMPLES); + if (fmt >= firstMultiOnlyFormat && (samples.length == 0 || samples[0] < maxSamples)) { + testFailed("the maximum value in SAMPLES should be at least " + maxSamples); + return; + } + + var prevSampleCount = 0; + var sampleCount; + for (var ndx = 0; ndx < samples.length; ++ndx, prevSampleCount = sampleCount) { + sampleCount = samples[ndx]; + // sample count must be > 0 + if (sampleCount <= 0) { + testFailed("Expected sample count to be at least one; got " + sampleCount); + return; + } + + // samples must be ordered descending + if (ndx > 0 && sampleCount >= prevSampleCount) { + testFailed("Expected sample count to be ordered in descending order; got " + prevSampleCount + " at index " + (ndx - 1) + ", and " + sampleCount + " at index " + ndx); + return; + } + } + } + testPassed("Internal format query succeeded"); +} + +function runCopyTexImageTest(enabled) +{ + var width = 16; + var height = 16; + var level = 0; + var cases = [ + { + internalformat: "RGBA16F", + format: "RGBA", + type: "HALF_FLOAT", + destInternalformat: "R16F", + data: new Uint16Array(width * height * 4) + }, + { + internalformat: "RGBA32F", + format: "RGBA", + type: "FLOAT", + destInternalformat: "R32F", + data: new Float32Array(width * height * 4) + }, + { + internalformat: "RGBA16F", + format: "RGBA", + type: "HALF_FLOAT", + destInternalformat: "RG16F", + data: new Uint16Array(width * height * 4) + }, + { + internalformat: "RGBA32F", + format: "RGBA", + type: "FLOAT", + destInternalformat: "RG32F", + data: new Float32Array(width * height * 4) + }, + { + internalformat: "RGBA16F", + format: "RGBA", + type: "HALF_FLOAT", + destInternalformat: "RGB16F", + data: new Uint16Array(width * height * 4) + }, + { + internalformat: "RGBA32F", + format: "RGBA", + type: "FLOAT", + destInternalformat: "RGB32F", + data: new Float32Array(width * height * 4) + }, + { + internalformat: "RGBA16F", + format: "RGBA", + type: "HALF_FLOAT", + destInternalformat: "RGBA16F", + data: new Uint16Array(width * height * 4) + }, + { + internalformat: "RGBA32F", + format: "RGBA", + type: "FLOAT", + destInternalformat: "RGBA32F", + data: new Float32Array(width * height * 4) + }, + { + internalformat: "R11F_G11F_B10F", + format: "RGB", + type: "FLOAT", + destInternalformat: "R11F_G11F_B10F", + data: new Float32Array(width * height * 3) + } + ]; + cases.forEach(function(testcase) { + debug(""); + debug("Testing CopyTexImage2D for internalformat: " + testcase.destInternalformat); + + var internalformat = gl[testcase.internalformat]; + var format = gl[testcase.format]; + var type = gl[testcase.type]; + var destInternalformat = gl[testcase.destInternalformat]; + var texSrc = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, texSrc); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + var data = testcase.data; + gl.texImage2D(gl.TEXTURE_2D, level, internalformat, width, height, 0, format, type, data); + var fbo = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texSrc, level); + var texDest = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, texDest); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setup framebuffer with texture should succeed."); + if (enabled) { + shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE"); + gl.copyTexImage2D(gl.TEXTURE_2D, level, destInternalformat, 0, 0, width, height, 0); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "CopyTexImage2D should succeed."); + } else { + shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT"); + gl.copyTexImage2D(gl.TEXTURE_2D, level, destInternalformat, 0, 0, width, height, 0); + wtu.glErrorShouldBe(gl, [gl.INVALID_ENUM, gl.INVALID_FRAMEBUFFER_OPERATION], "CopyTexImage2D should fail."); + } + + gl.deleteTexture(texDest); + gl.deleteTexture(texSrc); + gl.deleteFramebuffer(fbo); + }); +} + +description("This test verifies the functionality of the EXT_color_buffer_float extension, if it is available."); + +debug(""); + +var wtu = WebGLTestUtils; +var canvas = document.getElementById("canvas"); +var gl = wtu.create3DContext(canvas, null, 2); + +if (!gl) { + testFailed("WebGL context does not exist"); +} else { + testPassed("WebGL context exists"); + + var texturedShaders = [ + wtu.simpleTextureVertexShader, + "testFragmentShader" + ]; + var testProgram = + wtu.setupProgram(gl, + texturedShaders, + ['vPosition', 'texCoord0'], + [0, 1]); + var quadParameters = wtu.setupUnitQuad(gl, 0, 1); + + // Ensure these formats can't be used for rendering if the extension is disabled + runFloatTextureRenderTargetTest(false, gl.R16F, gl.RED); + runFloatTextureRenderTargetTest(false, gl.RG16F, gl.RG); + runFloatTextureRenderTargetTest(false, gl.RGBA16F, gl.RGBA); + runFloatTextureRenderTargetTest(false, gl.R32F, gl.RED); + runFloatTextureRenderTargetTest(false, gl.RG32F, gl.RG); + runFloatTextureRenderTargetTest(false, gl.RGBA32F, gl.RGBA); + runFloatTextureRenderTargetTest(false, gl.R11F_G11F_B10F, gl.RGB); + + runFloatRenderbufferRenderTargetTest(false, gl.R16F); + runFloatRenderbufferRenderTargetTest(false, gl.RG16F); + runFloatRenderbufferRenderTargetTest(false, gl.RGBA16F); + runFloatRenderbufferRenderTargetTest(false, gl.R32F); + runFloatRenderbufferRenderTargetTest(false, gl.RG32F); + runFloatRenderbufferRenderTargetTest(false, gl.RGBA32F); + runFloatRenderbufferRenderTargetTest(false, gl.R11F_G11F_B10F); + + // Ensure RGB16F can't be used for rendering. + runRGB16FNegativeTest(); + + runCopyTexImageTest(false); + + if (!gl.getExtension("EXT_color_buffer_float")) { + testPassed("No EXT_color_buffer_float support -- this is legal"); + } else { + testPassed("Successfully enabled EXT_color_buffer_float extension"); + + runInternalFormatQueryTest(); + + runFloatTextureRenderTargetTest(true, gl.R16F, gl.RED, testProgram, 1, [1000, 1, 1, 1], 0); + runFloatTextureRenderTargetTest(true, gl.RG16F, gl.RG, testProgram, 2, [1000, 1000, 1, 1], 0); + runFloatTextureRenderTargetTest(true, gl.RGBA16F, gl.RGBA, testProgram, 4, [1000, 1000, 1000, 1000], 0); + runFloatTextureRenderTargetTest(true, gl.R32F, gl.RED, testProgram, 1, [1000, 1, 1, 1], 0); + runFloatTextureRenderTargetTest(true, gl.RG32F, gl.RG, testProgram, 2, [1000, 1000, 1, 1], 0); + runFloatTextureRenderTargetTest(true, gl.RGBA32F, gl.RGBA, testProgram, 4, [1000, 1000, 1000, 1000], 0); + runFloatTextureRenderTargetTest(true, gl.R11F_G11F_B10F, gl.RGB, testProgram, 3, [1000, 1000, 1000, 1], 0); + runFloatTextureRenderTargetTest(true, gl.RGBA32F, gl.RGBA, testProgram, 4, [1000, 1000, 1000, 1000], 1); + runFloatTextureRenderTargetTest(true, gl.RGBA32F, gl.RGBA, testProgram, 4, [1000, 1000, 1000, 1000], 0.5); + + runFloatRenderbufferRenderTargetTest(true, gl.R16F, testProgram, 1, [1000, 1, 1, 1]); + runFloatRenderbufferRenderTargetTest(true, gl.RG16F, testProgram, 2, [1000, 1000, 1, 1]); + runFloatRenderbufferRenderTargetTest(true, gl.RGBA16F, testProgram, 4, [1000, 1000, 1000, 1000]); + runFloatRenderbufferRenderTargetTest(true, gl.R32F, testProgram, 1, [1000, 1, 1, 1]); + runFloatRenderbufferRenderTargetTest(true, gl.RG32F, testProgram, 2, [1000, 1000, 1, 1]); + runFloatRenderbufferRenderTargetTest(true, gl.RGBA32F, testProgram, 4, [1000, 1000, 1000, 1000]); + runFloatRenderbufferRenderTargetTest(true, gl.R11F_G11F_B10F, testProgram, 3, [1000, 1000, 1000, 1]); + + // Ensure EXT_color_buffer_float does not enable RGB16F as color renderable. + runRGB16FNegativeTest(); + + runCopyTexImageTest(true); + + runUniqueObjectTest(); + } +} + +debug(""); +var successfullyParsed = true; +</script> +<script src="../../js/js-test-post.js"></script> + +</body> +</html> |