ext-texture-mirror-clamp-to-edge.html (8343B)
1 <!-- 2 Copyright (c) 2023 The Khronos Group Inc. 3 Use of this source code is governed by an MIT-style license that can be 4 found in the LICENSE.txt file. 5 --> 6 7 <!DOCTYPE html> 8 <html> 9 <head> 10 <meta charset="utf-8"> 11 <title>WebGL EXT_texture_mirror_clamp_to_edge Conformance Tests</title> 12 <link rel="stylesheet" href="../../resources/js-test-style.css"/> 13 <script src="../../js/js-test-pre.js"></script> 14 <script src="../../js/webgl-test-utils.js"></script> 15 </head> 16 <body> 17 <canvas width="32" height="32" id="c"></canvas> 18 <div id="description"></div> 19 <div id="console"></div> 20 <script> 21 "use strict"; 22 description("This test verifies the functionality of the EXT_texture_mirror_clamp_to_edge extension, if it is available."); 23 24 debug(""); 25 26 var wtu = WebGLTestUtils; 27 var gl = wtu.create3DContext("c"); 28 const w = gl.drawingBufferWidth; 29 const h = gl.drawingBufferHeight; 30 var ext; 31 var sampler; 32 33 const pnames = ['TEXTURE_WRAP_S', 'TEXTURE_WRAP_T']; 34 if (gl.TEXTURE_WRAP_R) { 35 pnames.push('TEXTURE_WRAP_R'); 36 } 37 38 function runTestNoExtension() { 39 debug(""); 40 debug("Check the texture parameter without the extension"); 41 42 const tex = gl.createTexture(); 43 gl.bindTexture(gl.TEXTURE_2D, tex); 44 45 const MIRROR_CLAMP_TO_EDGE_EXT = 0x8743; 46 47 for (const pname of pnames) { 48 gl.texParameteri(gl.TEXTURE_2D, gl[pname], MIRROR_CLAMP_TO_EDGE_EXT); 49 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, `value unknown for ${pname} via texParameteri without enabling the extension`); 50 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no more errors"); 51 gl.texParameterf(gl.TEXTURE_2D, gl[pname], MIRROR_CLAMP_TO_EDGE_EXT); 52 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, `value unknown for ${pname} via texParameterf without enabling the extension`); 53 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no more errors"); 54 } 55 56 if (!gl.createSampler) return; 57 58 const sampler = gl.createSampler(); 59 for (const pname of pnames) { 60 gl.samplerParameteri(sampler, gl[pname], MIRROR_CLAMP_TO_EDGE_EXT); 61 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, `value unknown for ${pname} via samplerParameteri without enabling the extension`); 62 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no more errors"); 63 gl.samplerParameterf(sampler, gl[pname], MIRROR_CLAMP_TO_EDGE_EXT); 64 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, `value unknown for ${pname} via samplerParameterf without enabling the extension`); 65 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no more errors"); 66 } 67 } 68 69 function checkEnums() { 70 debug(""); 71 debug("Check enums"); 72 shouldBe("ext.MIRROR_CLAMP_TO_EDGE_EXT", "0x8743"); 73 } 74 75 function checkQueries() { 76 debug(""); 77 debug("Check texture and sampler state updates"); 78 79 const tex = gl.createTexture(); 80 gl.bindTexture(gl.TEXTURE_2D, tex); 81 82 for (const pname of pnames) { 83 gl.texParameteri(gl.TEXTURE_2D, gl[pname], ext.MIRROR_CLAMP_TO_EDGE_EXT); 84 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from texParameteri"); 85 shouldBe(`gl.getTexParameter(gl.TEXTURE_2D, gl.${pname})`, "ext.MIRROR_CLAMP_TO_EDGE_EXT"); 86 gl.texParameteri(gl.TEXTURE_2D, gl[pname], gl.REPEAT); 87 88 gl.texParameterf(gl.TEXTURE_2D, gl[pname], ext.MIRROR_CLAMP_TO_EDGE_EXT); 89 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from texParameterf"); 90 shouldBe(`gl.getTexParameter(gl.TEXTURE_2D, gl.${pname})`, "ext.MIRROR_CLAMP_TO_EDGE_EXT"); 91 gl.texParameterf(gl.TEXTURE_2D, gl[pname], gl.REPEAT); 92 } 93 94 if (!gl.createSampler) return; 95 96 sampler = gl.createSampler(); 97 for (const pname of pnames) { 98 gl.samplerParameteri(sampler, gl[pname], ext.MIRROR_CLAMP_TO_EDGE_EXT); 99 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from samplerParameteri"); 100 shouldBe(`gl.getSamplerParameter(sampler, gl.${pname})`, "ext.MIRROR_CLAMP_TO_EDGE_EXT"); 101 gl.samplerParameteri(sampler, gl[pname], gl.REPEAT); 102 103 gl.samplerParameterf(sampler, gl[pname], ext.MIRROR_CLAMP_TO_EDGE_EXT); 104 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from samplerParameterf"); 105 shouldBe(`gl.getSamplerParameter(sampler, gl.${pname})`, "ext.MIRROR_CLAMP_TO_EDGE_EXT"); 106 gl.samplerParameterf(sampler, gl[pname], gl.REPEAT); 107 } 108 } 109 110 function checkSampling() { 111 debug(""); 112 debug(`Check texture sampling with mirror-clamp-to-edge mode`); 113 114 wtu.setupUnitQuad(gl); 115 const vs = `precision highp float; 116 attribute vec4 vPosition; 117 varying vec2 texCoord; 118 void main() { 119 gl_Position = vec4(vPosition.xy, 0.0, 1.0); 120 texCoord = vPosition.xy * 2.0; 121 }`; 122 const program = wtu.setupProgram(gl, [vs, wtu.simpleTextureFragmentShader]); 123 gl.useProgram(program); 124 125 const black = [ 0, 0, 0, 255]; 126 const red = [255, 0, 0, 255]; 127 const green = [ 0, 255, 0, 255]; 128 const blue = [ 0, 0, 255, 255]; 129 const data = new Uint8Array([...black, ...red, ...green, ...blue]); 130 131 function checkPixels() { 132 function checkPixel(x, y, color) { 133 const screen = (s, t) => s * (t * 0.5 + 0.5); 134 wtu.checkCanvasRect(gl, screen(w, x), screen(h, y), 1, 1, color, 135 `(${x.toFixed(3)}, ${y.toFixed(3)}): ${color} `); 136 } 137 for (const signX of [+1, -1]) { 138 for (const signY of [+1, -1]) { 139 // This function expects screen-space coordinates 140 // normalized to [-1, +1]. The region from [0, 0] 141 // to [+1, +1] behaves like regular clamp-to-edge. 142 // Other three quadrants should be mirrored. 143 checkPixel(signX * 0.125, signY * 0.125, black); 144 checkPixel(signX * 0.375, signY * 0.125, red); 145 checkPixel(signX * 0.750, signY * 0.125, red); 146 checkPixel(signX * 0.125, signY * 0.375, green); 147 checkPixel(signX * 0.125, signY * 0.750, green); 148 checkPixel(signX * 0.375, signY * 0.375, blue); 149 checkPixel(signX * 0.750, signY * 0.375, blue); 150 checkPixel(signX * 0.375, signY * 0.750, blue); 151 checkPixel(signX * 0.750, signY * 0.750, blue); 152 } 153 } 154 } 155 156 const tex = gl.createTexture(); 157 gl.bindTexture(gl.TEXTURE_2D, tex); 158 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, data); 159 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, ext.MIRROR_CLAMP_TO_EDGE_EXT); 160 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, ext.MIRROR_CLAMP_TO_EDGE_EXT); 161 162 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 163 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 164 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texture created and configured"); 165 166 wtu.drawUnitQuad(gl); 167 checkPixels(); 168 169 if (!gl.createSampler) return; 170 171 debug(""); 172 debug(`Check texture sampling with mirror-clamp-to-edge mode using a sampler object`); 173 174 const texWithSampler = gl.createTexture(); 175 gl.bindTexture(gl.TEXTURE_2D, texWithSampler); 176 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, data); 177 178 sampler = gl.createSampler(); 179 gl.bindSampler(0, sampler); 180 gl.samplerParameteri(sampler, gl.TEXTURE_WRAP_S, ext.MIRROR_CLAMP_TO_EDGE_EXT); 181 gl.samplerParameteri(sampler, gl.TEXTURE_WRAP_T, ext.MIRROR_CLAMP_TO_EDGE_EXT); 182 gl.samplerParameteri(sampler, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 183 gl.samplerParameteri(sampler, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 184 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texture created and sampler configured"); 185 186 wtu.drawUnitQuad(gl); 187 checkPixels(); 188 } 189 190 function runTest() { 191 if (!gl) { 192 testFailed("context does not exist"); 193 return; 194 } 195 testPassed("context exists"); 196 197 runTestNoExtension(); 198 199 ext = gl.getExtension("EXT_texture_mirror_clamp_to_edge"); 200 wtu.runExtensionSupportedTest(gl, "EXT_texture_mirror_clamp_to_edge", ext !== null); 201 202 if (ext !== null) { 203 checkEnums(); 204 checkQueries(); 205 checkSampling(); 206 } else { 207 testPassed("No EXT_texture_mirror_clamp_to_edge support -- this is legal"); 208 } 209 } 210 211 runTest(); 212 213 var successfullyParsed = true; 214 </script> 215 <script src="../../js/js-test-post.js"></script> 216 </body> 217 </html>