Wed, 31 Dec 2014 06:55:50 +0100
Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2
michael@0 | 1 | <!DOCTYPE html> |
michael@0 | 2 | <html> |
michael@0 | 3 | <head> |
michael@0 | 4 | <meta charset="utf-8"/> |
michael@0 | 5 | <link rel="stylesheet" href="../../resources/js-test-style.css"/> |
michael@0 | 6 | <script src="../../resources/js-test-pre.js"></script> |
michael@0 | 7 | <script src="../resources/webgl-test.js"></script> |
michael@0 | 8 | <script src="../resources/webgl-test-utils.js"></script> |
michael@0 | 9 | </head> |
michael@0 | 10 | <body> |
michael@0 | 11 | <div id="description"></div> |
michael@0 | 12 | <div id="console"></div> |
michael@0 | 13 | <canvas id="canvas" width="16" height="16" style="width: 50px; height: 50px; border: 1px solid black;"></canvas> |
michael@0 | 14 | |
michael@0 | 15 | <!-- Shaders to test output --> |
michael@0 | 16 | <script id="vertexShader" type="x-shader/x-vertex"> |
michael@0 | 17 | attribute vec4 aPosition; |
michael@0 | 18 | void main() { |
michael@0 | 19 | gl_Position = aPosition; |
michael@0 | 20 | } |
michael@0 | 21 | </script> |
michael@0 | 22 | |
michael@0 | 23 | <script id="fragmentShader" type="x-shader/x-fragment"> |
michael@0 | 24 | precision mediump float; |
michael@0 | 25 | uniform float uColor; |
michael@0 | 26 | void main() { |
michael@0 | 27 | gl_FragColor = vec4(uColor, uColor, uColor, 1); |
michael@0 | 28 | } |
michael@0 | 29 | </script> |
michael@0 | 30 | |
michael@0 | 31 | <script> |
michael@0 | 32 | "use strict"; |
michael@0 | 33 | |
michael@0 | 34 | var wtu = WebGLTestUtils; |
michael@0 | 35 | var canvas; |
michael@0 | 36 | var gl; |
michael@0 | 37 | var ext = null; |
michael@0 | 38 | |
michael@0 | 39 | function getExtension() { |
michael@0 | 40 | ext = gl.getExtension("EXT_sRGB"); |
michael@0 | 41 | } |
michael@0 | 42 | |
michael@0 | 43 | function listsExtension() { |
michael@0 | 44 | var supported = gl.getSupportedExtensions(); |
michael@0 | 45 | return (supported.indexOf("EXT_sRGB") >= 0); |
michael@0 | 46 | } |
michael@0 | 47 | |
michael@0 | 48 | function readLocation(x, y) { |
michael@0 | 49 | var pixel = new Uint8Array(1 * 1 * 4); |
michael@0 | 50 | var px = Math.floor(x * canvas.drawingBufferWidth); |
michael@0 | 51 | var py = Math.floor(y * canvas.drawingBufferHeight); |
michael@0 | 52 | gl.readPixels(px, py, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel); |
michael@0 | 53 | return pixel; |
michael@0 | 54 | } |
michael@0 | 55 | |
michael@0 | 56 | function toVec3String(val) { |
michael@0 | 57 | if (typeof(val) == 'number') { |
michael@0 | 58 | return toVec3String([val, val, val]); |
michael@0 | 59 | } |
michael@0 | 60 | return '[' + val[0] + ', ' + val[1] + ', ' + val[2] + ']'; |
michael@0 | 61 | } |
michael@0 | 62 | |
michael@0 | 63 | var e = 2; // Amount of variance to allow in result pixels - may need to be tweaked higher |
michael@0 | 64 | |
michael@0 | 65 | function expectResult(target, successMessage, failureMessage) { |
michael@0 | 66 | var anyDiffer = false; |
michael@0 | 67 | var source = readLocation(0.5, 0.5); |
michael@0 | 68 | for (var m = 0; m < 3; m++) { |
michael@0 | 69 | if (Math.abs(source[m] - target) > e) { |
michael@0 | 70 | anyDiffer = true; |
michael@0 | 71 | testFailed(failureMessage + "; should be " + toVec3String(target) + ", was " + toVec3String(source)); |
michael@0 | 72 | break; |
michael@0 | 73 | } |
michael@0 | 74 | } |
michael@0 | 75 | |
michael@0 | 76 | if (!anyDiffer) { |
michael@0 | 77 | testPassed(successMessage); |
michael@0 | 78 | } |
michael@0 | 79 | } |
michael@0 | 80 | |
michael@0 | 81 | function createGreysRGBTexture(gl, color) { |
michael@0 | 82 | var numPixels = gl.drawingBufferWidth * gl.drawingBufferHeight; |
michael@0 | 83 | var size = numPixels * 3; |
michael@0 | 84 | var buf = new Uint8Array(size); |
michael@0 | 85 | for (var ii = 0; ii < numPixels; ++ii) { |
michael@0 | 86 | var off = ii * 3; |
michael@0 | 87 | buf[off + 0] = color; |
michael@0 | 88 | buf[off + 1] = color; |
michael@0 | 89 | buf[off + 2] = color; |
michael@0 | 90 | } |
michael@0 | 91 | |
michael@0 | 92 | var tex = gl.createTexture(); |
michael@0 | 93 | gl.bindTexture(gl.TEXTURE_2D, tex); |
michael@0 | 94 | gl.texImage2D(gl.TEXTURE_2D, |
michael@0 | 95 | 0, |
michael@0 | 96 | ext.SRGB_EXT, |
michael@0 | 97 | gl.drawingBufferWidth, |
michael@0 | 98 | gl.drawingBufferHeight, |
michael@0 | 99 | 0, |
michael@0 | 100 | ext.SRGB_EXT, |
michael@0 | 101 | gl.UNSIGNED_BYTE, |
michael@0 | 102 | buf); |
michael@0 | 103 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); |
michael@0 | 104 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); |
michael@0 | 105 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); |
michael@0 | 106 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); |
michael@0 | 107 | return tex; |
michael@0 | 108 | } |
michael@0 | 109 | |
michael@0 | 110 | function testValidFormat(fn, internalFormat, formatName) { |
michael@0 | 111 | fn(internalFormat); |
michael@0 | 112 | glErrorShouldBe(gl, gl.NO_ERROR, "was able to create type " + formatName); |
michael@0 | 113 | } |
michael@0 | 114 | |
michael@0 | 115 | function testInvalidFormat(fn, internalFormat, formatName) { |
michael@0 | 116 | fn(internalFormat); |
michael@0 | 117 | var err = gl.getError(); |
michael@0 | 118 | if (err == gl.NO_ERROR) { |
michael@0 | 119 | testFailed("should NOT be able to create type " + formatName); |
michael@0 | 120 | } else if (err == gl.INVALID_OPERATION) { |
michael@0 | 121 | testFailed("should return gl.INVALID_ENUM for type " + formatName); |
michael@0 | 122 | } else if (err == gl.INVALID_ENUM) { |
michael@0 | 123 | testPassed("not able to create invalid format: " + formatName); |
michael@0 | 124 | } |
michael@0 | 125 | } |
michael@0 | 126 | |
michael@0 | 127 | var textureFormatFixture = { |
michael@0 | 128 | desc: "Checking texture formats", |
michael@0 | 129 | create: function(format) { |
michael@0 | 130 | var tex = gl.createTexture(); |
michael@0 | 131 | gl.bindTexture(gl.TEXTURE_2D, tex); |
michael@0 | 132 | gl.texImage2D(gl.TEXTURE_2D, |
michael@0 | 133 | 0, // level |
michael@0 | 134 | format, // internalFormat |
michael@0 | 135 | gl.drawingBufferWidth, // width |
michael@0 | 136 | gl.drawingBufferHeight, // height |
michael@0 | 137 | 0, // border |
michael@0 | 138 | format, // format |
michael@0 | 139 | gl.UNSIGNED_BYTE, // type |
michael@0 | 140 | null); // data |
michael@0 | 141 | }, |
michael@0 | 142 | tests: [ |
michael@0 | 143 | { |
michael@0 | 144 | desc: "Checking valid formats", |
michael@0 | 145 | fn: testValidFormat, |
michael@0 | 146 | formats: [ 'SRGB_EXT', 'SRGB_ALPHA_EXT' ] |
michael@0 | 147 | }, |
michael@0 | 148 | { |
michael@0 | 149 | desc: "Checking invalid formats", |
michael@0 | 150 | fn: testInvalidFormat, |
michael@0 | 151 | formats: [ 'SRGB8_ALPHA8_EXT' ] |
michael@0 | 152 | } |
michael@0 | 153 | ] |
michael@0 | 154 | }; |
michael@0 | 155 | |
michael@0 | 156 | var renderbufferFormatFixture = { |
michael@0 | 157 | desc: "Checking renderbuffer formats", |
michael@0 | 158 | create: function(format) { |
michael@0 | 159 | var rbo = gl.createRenderbuffer(); |
michael@0 | 160 | gl.bindRenderbuffer(gl.RENDERBUFFER, rbo); |
michael@0 | 161 | gl.renderbufferStorage(gl.RENDERBUFFER, |
michael@0 | 162 | format, |
michael@0 | 163 | gl.drawingBufferWidth, |
michael@0 | 164 | gl.drawingBufferHeight); |
michael@0 | 165 | }, |
michael@0 | 166 | tests: [ |
michael@0 | 167 | { |
michael@0 | 168 | desc: "Checking valid formats", |
michael@0 | 169 | fn: testValidFormat, |
michael@0 | 170 | formats: [ 'SRGB8_ALPHA8_EXT' ] |
michael@0 | 171 | }, |
michael@0 | 172 | { |
michael@0 | 173 | desc: "Checking invalid formats", |
michael@0 | 174 | fn: testInvalidFormat, |
michael@0 | 175 | formats: [ 'SRGB_EXT', 'SRGB_ALPHA_EXT' ] |
michael@0 | 176 | } |
michael@0 | 177 | ] |
michael@0 | 178 | }; |
michael@0 | 179 | |
michael@0 | 180 | |
michael@0 | 181 | description("Test sRGB texture support"); |
michael@0 | 182 | |
michael@0 | 183 | debug(""); |
michael@0 | 184 | debug("Canvas.getContext"); |
michael@0 | 185 | |
michael@0 | 186 | canvas = document.getElementById("canvas"); |
michael@0 | 187 | gl = wtu.create3DContext(canvas); |
michael@0 | 188 | if (!gl) { |
michael@0 | 189 | testFailed("context does not exist"); |
michael@0 | 190 | } else { |
michael@0 | 191 | testPassed("context exists"); |
michael@0 | 192 | |
michael@0 | 193 | debug(""); |
michael@0 | 194 | debug("Checking sRGB texture support"); |
michael@0 | 195 | |
michael@0 | 196 | // Query the extension and store globally so shouldBe can access it |
michael@0 | 197 | ext = gl.getExtension("EXT_sRGB"); |
michael@0 | 198 | |
michael@0 | 199 | if (!ext) { |
michael@0 | 200 | testPassed("No EXT_sRGB support -- this is legal"); |
michael@0 | 201 | |
michael@0 | 202 | runSupportedTest(false); |
michael@0 | 203 | } else { |
michael@0 | 204 | testPassed("Successfully enabled EXT_sRGB extension"); |
michael@0 | 205 | |
michael@0 | 206 | runSupportedTest(true); |
michael@0 | 207 | |
michael@0 | 208 | gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); |
michael@0 | 209 | |
michael@0 | 210 | runFormatTest(textureFormatFixture); |
michael@0 | 211 | runFormatTest(renderbufferFormatFixture); |
michael@0 | 212 | runTextureReadConversionTest(); |
michael@0 | 213 | runFramebufferTextureConversionTest(); |
michael@0 | 214 | runFramebufferRenderbufferConversionTest(); |
michael@0 | 215 | } |
michael@0 | 216 | } |
michael@0 | 217 | |
michael@0 | 218 | function runSupportedTest(extensionEnabled) { |
michael@0 | 219 | if (listsExtension()) { |
michael@0 | 220 | if (extensionEnabled) { |
michael@0 | 221 | testPassed("EXT_sRGB listed as supported and getExtension succeeded"); |
michael@0 | 222 | } else { |
michael@0 | 223 | testFailed("EXT_sRGB listed as supported but getExtension failed"); |
michael@0 | 224 | } |
michael@0 | 225 | } else { |
michael@0 | 226 | if (extensionEnabled) { |
michael@0 | 227 | testFailed("EXT_sRGB not listed as supported but getExtension succeeded"); |
michael@0 | 228 | } else { |
michael@0 | 229 | testPassed("EXT_sRGB not listed as supported and getExtension failed -- this is legal"); |
michael@0 | 230 | } |
michael@0 | 231 | } |
michael@0 | 232 | } |
michael@0 | 233 | |
michael@0 | 234 | function runFormatTest(fixture) { |
michael@0 | 235 | debug(""); |
michael@0 | 236 | debug(fixture.desc); |
michael@0 | 237 | |
michael@0 | 238 | for (var tt = 0; tt < fixture.tests.length; ++tt) { |
michael@0 | 239 | var test = fixture.tests[tt]; |
michael@0 | 240 | debug(test.desc); |
michael@0 | 241 | |
michael@0 | 242 | for (var ii = 0; ii < test.formats.length; ++ii) { |
michael@0 | 243 | var formatName = test.formats[ii]; |
michael@0 | 244 | test.fn(fixture.create, ext[formatName], "ext." + formatName); |
michael@0 | 245 | } |
michael@0 | 246 | |
michael@0 | 247 | if (tt != fixture.tests.length - 1) |
michael@0 | 248 | debug(""); |
michael@0 | 249 | } |
michael@0 | 250 | } |
michael@0 | 251 | |
michael@0 | 252 | function runTextureReadConversionTest() { |
michael@0 | 253 | debug(""); |
michael@0 | 254 | debug("Test the conversion of colors from sRGB to linear on texture read"); |
michael@0 | 255 | |
michael@0 | 256 | // Draw |
michael@0 | 257 | var conversions = [ |
michael@0 | 258 | [ 0, 0 ], |
michael@0 | 259 | [ 63, 13 ], |
michael@0 | 260 | [ 127, 54 ], |
michael@0 | 261 | [ 191, 133 ], |
michael@0 | 262 | [ 255, 255 ] |
michael@0 | 263 | ]; |
michael@0 | 264 | |
michael@0 | 265 | var program = wtu.setupTexturedQuad(gl); |
michael@0 | 266 | gl.uniform1i(gl.getUniformLocation(program, "tex2d"), 0); |
michael@0 | 267 | |
michael@0 | 268 | for (var ii = 0; ii < conversions.length; ii++) { |
michael@0 | 269 | var tex = createGreysRGBTexture(gl, conversions[ii][0]); |
michael@0 | 270 | wtu.drawQuad(gl); |
michael@0 | 271 | expectResult(conversions[ii][1], |
michael@0 | 272 | "sRGB texture read returned correct data", |
michael@0 | 273 | "sRGB texture read returned incorrect data"); |
michael@0 | 274 | } |
michael@0 | 275 | } |
michael@0 | 276 | |
michael@0 | 277 | function runFramebufferTextureConversionTest() { |
michael@0 | 278 | debug(""); |
michael@0 | 279 | debug("Test the conversion of colors from linear to sRGB on framebuffer (texture) write"); |
michael@0 | 280 | |
michael@0 | 281 | var program = wtu.setupProgram(gl, ['vertexShader', 'fragmentShader'], ['aPosition'], [0]); |
michael@0 | 282 | var tex = createGreysRGBTexture(gl, 0); |
michael@0 | 283 | var fbo = gl.createFramebuffer(); |
michael@0 | 284 | gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); |
michael@0 | 285 | gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0); |
michael@0 | 286 | glErrorShouldBe(gl, gl.NO_ERROR); |
michael@0 | 287 | |
michael@0 | 288 | shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT)', 'ext.SRGB_EXT'); |
michael@0 | 289 | shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE"); |
michael@0 | 290 | |
michael@0 | 291 | // Draw |
michael@0 | 292 | var conversions = [ |
michael@0 | 293 | [ 0, 0 ], |
michael@0 | 294 | [ 13, 63 ], |
michael@0 | 295 | [ 54, 127 ], |
michael@0 | 296 | [ 133, 191 ], |
michael@0 | 297 | [ 255, 255 ] |
michael@0 | 298 | ]; |
michael@0 | 299 | |
michael@0 | 300 | wtu.setupUnitQuad(gl, 0); |
michael@0 | 301 | |
michael@0 | 302 | for (var ii = 0; ii < conversions.length; ii++) { |
michael@0 | 303 | gl.uniform1f(gl.getUniformLocation(program, "uColor"), conversions[ii][0]/255.0); |
michael@0 | 304 | wtu.drawQuad(gl, [0, 0, 0, 0]); |
michael@0 | 305 | expectResult(conversions[ii][1], |
michael@0 | 306 | "framebuffer (texture) read returned correct data", |
michael@0 | 307 | "framebuffer (texture) read returned incorrect data"); |
michael@0 | 308 | } |
michael@0 | 309 | |
michael@0 | 310 | gl.bindFramebuffer(gl.FRAMEBUFFER, null); |
michael@0 | 311 | } |
michael@0 | 312 | |
michael@0 | 313 | function runFramebufferRenderbufferConversionTest() { |
michael@0 | 314 | debug(""); |
michael@0 | 315 | debug("Test the conversion of colors from linear to sRGB on framebuffer (renderbuffer) write"); |
michael@0 | 316 | |
michael@0 | 317 | function createsRGBFramebuffer(gl, width, height) { |
michael@0 | 318 | var rbo = gl.createRenderbuffer(); |
michael@0 | 319 | gl.bindRenderbuffer(gl.RENDERBUFFER, rbo); |
michael@0 | 320 | gl.renderbufferStorage(gl.RENDERBUFFER, ext.SRGB8_ALPHA8_EXT, width, height); |
michael@0 | 321 | glErrorShouldBe(gl, gl.NO_ERROR); |
michael@0 | 322 | |
michael@0 | 323 | var fbo = gl.createFramebuffer(); |
michael@0 | 324 | gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); |
michael@0 | 325 | gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, |
michael@0 | 326 | gl.RENDERBUFFER, rbo); |
michael@0 | 327 | glErrorShouldBe(gl, gl.NO_ERROR); |
michael@0 | 328 | |
michael@0 | 329 | shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT)', 'ext.SRGB_EXT'); |
michael@0 | 330 | shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE"); |
michael@0 | 331 | |
michael@0 | 332 | return fbo; |
michael@0 | 333 | } |
michael@0 | 334 | |
michael@0 | 335 | // Draw |
michael@0 | 336 | var conversions = [ |
michael@0 | 337 | [ 0, 0 ], |
michael@0 | 338 | [ 13, 63 ], |
michael@0 | 339 | [ 54, 127 ], |
michael@0 | 340 | [ 133, 191 ], |
michael@0 | 341 | [ 255, 255 ] |
michael@0 | 342 | ]; |
michael@0 | 343 | |
michael@0 | 344 | var program = wtu.setupProgram(gl, ['vertexShader', 'fragmentShader'], ['aPosition'], [0]); |
michael@0 | 345 | wtu.setupUnitQuad(gl, 0); |
michael@0 | 346 | var fbo = createsRGBFramebuffer(gl, 4, 4); |
michael@0 | 347 | |
michael@0 | 348 | for (var ii = 0; ii < conversions.length; ii++) { |
michael@0 | 349 | gl.uniform1f(gl.getUniformLocation(program, "uColor"), conversions[ii][0]/255.0); |
michael@0 | 350 | wtu.drawQuad(gl, [0, 0, 0, 0]); |
michael@0 | 351 | expectResult(conversions[ii][1], |
michael@0 | 352 | "framebuffer (renderbuffer) read returned the correct data", |
michael@0 | 353 | "framebuffer (renderbuffer) read returned incorrect data"); |
michael@0 | 354 | } |
michael@0 | 355 | } |
michael@0 | 356 | |
michael@0 | 357 | debug(""); |
michael@0 | 358 | var successfullyParsed = true; |
michael@0 | 359 | </script> |
michael@0 | 360 | <script>finishTest();</script> |
michael@0 | 361 | |
michael@0 | 362 | </body> |
michael@0 | 363 | </html> |