ext-sRGB.html (15092B)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"/> 5 <link rel="stylesheet" href="../../resources/js-test-style.css"/> 6 <script src="../../js/js-test-pre.js"></script> 7 <script src="../../js/webgl-test-utils.js"></script> 8 </head> 9 <body> 10 <div id="description"></div> 11 <div id="console"></div> 12 <canvas id="canvas" width="16" height="16" style="width: 50px; height: 50px; border: 1px solid black;"></canvas> 13 14 <!-- Shaders to test output --> 15 <script id="vertexShader" type="x-shader/x-vertex"> 16 attribute vec4 aPosition; 17 void main() { 18 gl_Position = aPosition; 19 } 20 </script> 21 22 <script id="fragmentShader" type="x-shader/x-fragment"> 23 precision mediump float; 24 uniform float uColor; 25 void main() { 26 gl_FragColor = vec4(uColor, uColor, uColor, 1); 27 } 28 </script> 29 30 <script id="vshader" type="x-shader/x-vertex"> 31 attribute vec4 vPosition; 32 attribute vec2 texCoord0; 33 varying vec2 texCoord; 34 void main() 35 { 36 gl_Position = vPosition; 37 texCoord = texCoord0; 38 } 39 </script> 40 41 <script id="fshader" type="x-shader/x-fragment"> 42 precision mediump float; 43 uniform sampler2D tex; 44 varying vec2 texCoord; 45 void main() 46 { 47 gl_FragColor = texture2D(tex, texCoord); 48 } 49 </script> 50 51 <script> 52 "use strict"; 53 54 var wtu = WebGLTestUtils; 55 var canvas; 56 var gl; 57 var ext = null; 58 59 var extConstants = { 60 "SRGB_EXT": 0x8C40, 61 "SRGB_ALPHA_EXT": 0x8C42, 62 "SRGB8_ALPHA8_EXT": 0x8C43, 63 "FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT": 0x8210 64 }; 65 66 function getExtension() { 67 ext = gl.getExtension("EXT_sRGB"); 68 } 69 70 function listsExtension() { 71 var supported = gl.getSupportedExtensions(); 72 return (supported.indexOf("EXT_sRGB") >= 0); 73 } 74 75 function toVec3String(val) { 76 if (typeof(val) == 'number') { 77 return toVec3String([val, val, val]); 78 } 79 return '[' + val[0] + ', ' + val[1] + ', ' + val[2] + ']'; 80 } 81 82 var e = 2; // Amount of variance to allow in result pixels - may need to be tweaked higher 83 84 function expectResult(target) { 85 wtu.checkCanvasRect(gl, 86 Math.floor(gl.drawingBufferWidth / 2), 87 Math.floor(gl.drawingBufferHeight / 2), 88 1, 89 1, 90 [target, target, target, 255], 91 undefined, 92 e); 93 } 94 95 function createGreysRGBTexture(gl, color, format) { 96 var numPixels = gl.drawingBufferWidth * gl.drawingBufferHeight; 97 var elements; 98 switch (format) { 99 case ext.SRGB_EXT: elements = 3; break; 100 case ext.SRGB_ALPHA_EXT: elements = 4; break; 101 default: return null; 102 } 103 104 var size = numPixels * elements; 105 var buf = new Uint8Array(size); 106 for (var ii = 0; ii < numPixels; ++ii) { 107 var off = ii * elements; 108 buf[off + 0] = color; 109 buf[off + 1] = color; 110 buf[off + 2] = color; 111 if (format == ext.SRGB_ALPHA_EXT) { 112 buf[off + 3] = 255; 113 } 114 } 115 116 var tex = gl.createTexture(); 117 gl.bindTexture(gl.TEXTURE_2D, tex); 118 gl.texImage2D(gl.TEXTURE_2D, 119 0, 120 format, 121 gl.drawingBufferWidth, 122 gl.drawingBufferHeight, 123 0, 124 format, 125 gl.UNSIGNED_BYTE, 126 buf); 127 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); 128 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 129 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 130 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 131 return tex; 132 } 133 134 function testValidFormat(fn, internalFormat, formatName, enabled) { 135 if (enabled) { 136 fn(internalFormat); 137 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "was able to create type " + formatName); 138 } else { 139 testInvalidFormat(fn, internalFormat, formatName, enabled); 140 } 141 } 142 143 function testInvalidFormat(fn, internalFormat, formatName, enabled) { 144 fn(internalFormat); 145 var err = gl.getError(); 146 if (err == gl.NO_ERROR) { 147 testFailed("should NOT be able to create type " + formatName); 148 } else if (err == gl.INVALID_ENUM || err == gl.INVALID_VALUE) { 149 testPassed("not able to create invalid format: " + formatName); 150 } 151 } 152 153 var textureFormatFixture = { 154 desc: "Checking texture formats", 155 create: function(format) { 156 var tex = gl.createTexture(); 157 gl.bindTexture(gl.TEXTURE_2D, tex); 158 gl.texImage2D(gl.TEXTURE_2D, 159 0, // level 160 format, // internalFormat 161 gl.drawingBufferWidth, // width 162 gl.drawingBufferHeight, // height 163 0, // border 164 format, // format 165 gl.UNSIGNED_BYTE, // type 166 null); // data 167 }, 168 tests: [ 169 { 170 desc: "Checking valid formats", 171 fn: testValidFormat, 172 formats: [ 'SRGB_EXT', 'SRGB_ALPHA_EXT' ] 173 }, 174 { 175 desc: "Checking invalid formats", 176 fn: testInvalidFormat, 177 formats: [ 'SRGB8_ALPHA8_EXT' ] 178 } 179 ] 180 }; 181 182 var renderbufferFormatFixture = { 183 desc: "Checking renderbuffer formats", 184 create: function(format) { 185 var rbo = gl.createRenderbuffer(); 186 gl.bindRenderbuffer(gl.RENDERBUFFER, rbo); 187 gl.renderbufferStorage(gl.RENDERBUFFER, 188 format, 189 gl.drawingBufferWidth, 190 gl.drawingBufferHeight); 191 }, 192 tests: [ 193 { 194 desc: "Checking valid formats", 195 fn: testValidFormat, 196 formats: [ 'SRGB8_ALPHA8_EXT' ] 197 }, 198 { 199 desc: "Checking invalid formats", 200 fn: testInvalidFormat, 201 formats: [ 'SRGB_EXT', 'SRGB_ALPHA_EXT' ] 202 } 203 ] 204 }; 205 206 207 description("Test sRGB texture support"); 208 209 debug(""); 210 debug("Canvas.getContext"); 211 212 canvas = document.getElementById("canvas"); 213 gl = wtu.create3DContext(canvas); 214 if (!gl) { 215 testFailed("context does not exist"); 216 } else { 217 testPassed("context exists"); 218 219 debug(""); 220 debug("Checking sRGB texture support with extension disabled"); 221 222 runFormatTest(textureFormatFixture, false); 223 runFormatTest(renderbufferFormatFixture, false); 224 225 { 226 var fbo = gl.createFramebuffer(); 227 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); 228 229 debug("Checking getFramebufferAttachmentParameter with a renderbuffer"); 230 { 231 var rbo = gl.createRenderbuffer(); 232 gl.bindRenderbuffer(gl.RENDERBUFFER, rbo); 233 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGB565, 1, 1); 234 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo); 235 wtu.glErrorShouldBe(gl, gl.NO_ERROR); 236 shouldBeNull('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, 0x8210 /* FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT */)'); 237 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM); 238 gl.bindRenderbuffer(gl.RENDERBUFFER, null); 239 gl.deleteRenderbuffer(rbo); 240 } 241 242 debug("Checking getFramebufferAttachmentParameter with a texture"); 243 { 244 var tex = gl.createTexture(); 245 gl.bindTexture(gl.TEXTURE_2D, tex); 246 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 247 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0); 248 wtu.glErrorShouldBe(gl, gl.NO_ERROR); 249 shouldBeNull('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, 0x8210 /* FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT */)'); 250 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM); 251 gl.bindTexture(gl.TEXTURE_2D, null); 252 gl.deleteTexture(tex); 253 } 254 255 gl.bindFramebuffer(gl.FRAMEBUFFER, null); 256 gl.deleteFramebuffer(fbo); 257 } 258 259 debug(""); 260 debug("Checking sRGB texture support"); 261 262 // Query the extension and store globally so shouldBe can access it 263 ext = gl.getExtension("EXT_sRGB"); 264 265 if (!ext) { 266 testPassed("No EXT_sRGB support -- this is legal"); 267 268 runSupportedTest(false); 269 finishTest(); 270 } else { 271 testPassed("Successfully enabled EXT_sRGB extension"); 272 273 runSupportedTest(true); 274 275 gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); 276 277 runConstantsTest(); 278 runFormatTest(textureFormatFixture, true); 279 runFormatTest(renderbufferFormatFixture, true); 280 runTextureReadConversionTest(); 281 runFramebufferTextureConversionTest(ext.SRGB_EXT); 282 runFramebufferTextureConversionTest(ext.SRGB_ALPHA_EXT); 283 runFramebufferRenderbufferConversionTest(); 284 runGenerateMipmapTest(); 285 runLoadFromImageTest(function() { 286 finishTest(); 287 }); 288 } 289 } 290 291 function runConstantsTest() { 292 debug(""); 293 debug("Checking extension constants values"); 294 295 for (var constant in extConstants) { 296 if (constant in ext) { 297 if (extConstants[constant] != ext[constant]) { 298 testFailed("Value of " + constant + " should be: " + extConstants[constant] + ", was: " + ext[constant]); 299 } else { 300 testPassed("Value of " + constant + " was expected value: " + extConstants[constant]); 301 } 302 } else { 303 testFailed(constant + " not found in extension object"); 304 } 305 } 306 } 307 308 function runSupportedTest(extensionEnabled) { 309 if (listsExtension()) { 310 if (extensionEnabled) { 311 testPassed("EXT_sRGB listed as supported and getExtension succeeded"); 312 } else { 313 testFailed("EXT_sRGB listed as supported but getExtension failed"); 314 } 315 } else { 316 if (extensionEnabled) { 317 testFailed("EXT_sRGB not listed as supported but getExtension succeeded"); 318 } else { 319 testPassed("EXT_sRGB not listed as supported and getExtension failed -- this is legal"); 320 } 321 } 322 } 323 324 function runFormatTest(fixture, enabled) { 325 debug(""); 326 debug(fixture.desc); 327 328 for (var tt = 0; tt < fixture.tests.length; ++tt) { 329 var test = fixture.tests[tt]; 330 debug(test.desc); 331 332 for (var ii = 0; ii < test.formats.length; ++ii) { 333 var formatName = test.formats[ii]; 334 test.fn(fixture.create, extConstants[formatName], "ext." + formatName, enabled); 335 } 336 337 if (tt != fixture.tests.length - 1) 338 debug(""); 339 } 340 } 341 342 function runTextureReadConversionTest() { 343 debug(""); 344 debug("Test the conversion of colors from sRGB to linear on texture read"); 345 346 // Draw 347 var conversions = [ 348 [ 0, 0 ], 349 [ 63, 13 ], 350 [ 127, 54 ], 351 [ 191, 133 ], 352 [ 255, 255 ] 353 ]; 354 355 var program = wtu.setupTexturedQuad(gl); 356 gl.uniform1i(gl.getUniformLocation(program, "tex"), 0); 357 358 for (var ii = 0; ii < conversions.length; ii++) { 359 var tex = createGreysRGBTexture(gl, conversions[ii][0], ext.SRGB_EXT); 360 wtu.drawUnitQuad(gl); 361 expectResult(conversions[ii][1]); 362 } 363 } 364 365 function runFramebufferTextureConversionTest(format) { 366 var formatString; 367 var validFormat; 368 switch (format) { 369 case ext.SRGB_EXT: formatString = "sRGB"; validFormat = false; break; 370 case ext.SRGB_ALPHA_EXT: formatString = "sRGB_ALPHA"; validFormat = true; break; 371 default: return null; 372 } 373 debug(""); 374 debug("Test " + formatString + " framebuffer attachments." + (validFormat ? "" : " (Invalid)")); 375 376 var program = wtu.setupProgram(gl, ['vertexShader', 'fragmentShader'], ['aPosition'], [0]); 377 var tex = createGreysRGBTexture(gl, 0, format); 378 var fbo = gl.createFramebuffer(); 379 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); 380 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0); 381 wtu.glErrorShouldBe(gl, gl.NO_ERROR); 382 383 shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT)', 'ext.SRGB_EXT'); 384 385 if (validFormat) { 386 shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE"); 387 388 debug(""); 389 debug("Test the conversion of colors from linear to " + formatString + " on framebuffer (texture) write"); 390 391 // Draw 392 var conversions = [ 393 [ 0, 0 ], 394 [ 13, 63 ], 395 [ 54, 127 ], 396 [ 133, 191 ], 397 [ 255, 255 ] 398 ]; 399 400 wtu.setupUnitQuad(gl, 0); 401 402 for (var ii = 0; ii < conversions.length; ii++) { 403 gl.uniform1f(gl.getUniformLocation(program, "uColor"), conversions[ii][0]/255.0); 404 wtu.drawUnitQuad(gl, [0, 0, 0, 0]); 405 wtu.glErrorShouldBe(gl, gl.NO_ERROR); 406 expectResult(conversions[ii][1]); 407 } 408 } else { 409 shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT"); 410 411 wtu.setupUnitQuad(gl, 0); 412 gl.uniform1f(gl.getUniformLocation(program, "uColor"), 0.5); 413 wtu.drawUnitQuad(gl, [0, 0, 0, 0]); 414 wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION); 415 } 416 417 gl.bindFramebuffer(gl.FRAMEBUFFER, null); 418 } 419 420 function runFramebufferRenderbufferConversionTest() { 421 debug(""); 422 debug("Test the conversion of colors from linear to sRGB on framebuffer (renderbuffer) write"); 423 424 function createsRGBFramebuffer(gl, width, height) { 425 var rbo = gl.createRenderbuffer(); 426 gl.bindRenderbuffer(gl.RENDERBUFFER, rbo); 427 gl.renderbufferStorage(gl.RENDERBUFFER, ext.SRGB8_ALPHA8_EXT, width, height); 428 wtu.glErrorShouldBe(gl, gl.NO_ERROR); 429 430 var fbo = gl.createFramebuffer(); 431 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); 432 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, 433 gl.RENDERBUFFER, rbo); 434 wtu.glErrorShouldBe(gl, gl.NO_ERROR); 435 436 shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT)', 'ext.SRGB_EXT'); 437 shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE"); 438 439 return fbo; 440 } 441 442 // Draw 443 var conversions = [ 444 [ 0, 0 ], 445 [ 13, 63 ], 446 [ 54, 127 ], 447 [ 133, 191 ], 448 [ 255, 255 ] 449 ]; 450 451 var program = wtu.setupProgram(gl, ['vertexShader', 'fragmentShader'], ['aPosition'], [0]); 452 wtu.setupUnitQuad(gl, 0); 453 var fbo = createsRGBFramebuffer(gl, gl.drawingBufferWidth, gl.drawingBufferHeight); 454 455 for (var ii = 0; ii < conversions.length; ii++) { 456 gl.uniform1f(gl.getUniformLocation(program, "uColor"), conversions[ii][0]/255.0); 457 wtu.drawUnitQuad(gl, [0, 0, 0, 0]); 458 expectResult(conversions[ii][1]); 459 } 460 } 461 462 function runLoadFromImageTest(callback) { 463 debug(""); 464 debug("Tests to ensure that SRGB textures can successfully use image elements as their source"); 465 466 var img = wtu.makeImage("../../resources/gray-1024x1024.jpg", function() { 467 var tex = gl.createTexture(); 468 gl.bindTexture(gl.TEXTURE_2D, tex); 469 gl.texImage2D(gl.TEXTURE_2D, 0, ext.SRGB_EXT, ext.SRGB_EXT, gl.UNSIGNED_BYTE, img); 470 wtu.glErrorShouldBe(gl, gl.NO_ERROR); 471 472 gl.texImage2D(gl.TEXTURE_2D, 0, ext.SRGB_ALPHA_EXT, ext.SRGB_ALPHA_EXT, gl.UNSIGNED_BYTE, img); 473 wtu.glErrorShouldBe(gl, gl.NO_ERROR); 474 475 callback(); 476 }, function() { 477 testFailed("Image could not be loaded"); 478 callback(); 479 }); 480 } 481 482 function runGenerateMipmapTest() 483 { 484 debug(""); 485 debug("GenerateMipmaps for sRGB textures is forbidden"); 486 487 var tex = gl.createTexture(); 488 gl.bindTexture(gl.TEXTURE_2D, tex); 489 490 gl.texImage2D(gl.TEXTURE_2D, 0, ext.SRGB_ALPHA_EXT, 2, 2, 0, ext.SRGB_ALPHA_EXT, 491 gl.UNSIGNED_BYTE, null); 492 wtu.glErrorShouldBe(gl, gl.NO_ERROR); 493 gl.generateMipmap(gl.TEXTURE_2D); 494 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION); 495 496 gl.deleteTexture(tex); 497 } 498 499 var successfullyParsed = true; 500 </script> 501 </body> 502 </html>