oes-texture-float.html (23043B)
1 <!-- 2 Copyright (c) 2019 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>OES_texture_float/WEBGL_color_buffer_float</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 <script src="../../js/tests/ext-float-blend.js"></script> 16 </head> 17 <body> 18 <div id="description"></div> 19 <canvas id="canvas" style="width: 50px; height: 50px;"> </canvas> 20 <div id="console"></div> 21 <!-- Shaders for testing floating-point textures --> 22 <script id="testFragmentShader" type="x-shader/x-fragment"> 23 precision mediump float; 24 uniform sampler2D tex; 25 uniform vec4 subtractor; 26 varying vec2 texCoord; 27 void main() 28 { 29 vec4 color = texture2D(tex, texCoord); 30 if (abs(color.r - subtractor.r) + 31 abs(color.g - subtractor.g) + 32 abs(color.b - subtractor.b) + 33 abs(color.a - subtractor.a) < 8.0) { 34 gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); 35 } else { 36 gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); 37 } 38 } 39 </script> 40 <!-- Shaders for testing floating-point render targets --> 41 <script id="positionVertexShader" type="x-shader/x-vertex"> 42 attribute vec4 vPosition; 43 void main() 44 { 45 gl_Position = vPosition; 46 } 47 </script> 48 <script id="floatingPointFragmentShader" type="x-shader/x-fragment"> 49 void main() 50 { 51 gl_FragColor = vec4(10000.0, 10000.0, 10000.0, 10000.0); 52 } 53 </script> 54 <script> 55 "use strict"; 56 description("This test verifies the functionality of the OES_texture_float and WEBGL_color_buffer_float extensions, if available."); 57 58 debug(""); 59 60 var wtu = WebGLTestUtils; 61 var canvas = document.getElementById("canvas"); 62 var gl = wtu.create3DContext(canvas); 63 var ext = null; 64 65 if (!gl) { 66 testFailed("WebGL context does not exist"); 67 } else { 68 testPassed("WebGL context exists"); 69 70 var texturedShaders = [ 71 wtu.simpleTextureVertexShader, 72 "testFragmentShader" 73 ]; 74 var testProgram = 75 wtu.setupProgram(gl, 76 texturedShaders, 77 ['vPosition', 'texCoord0'], 78 [0, 1]); 79 var quadParameters = wtu.setupUnitQuad(gl, 0, 1); 80 81 // First verify that allocation of floating-point textures fails if 82 // the extension has not been enabled yet. 83 runTextureCreationTest(testProgram, false); 84 85 { 86 debug(""); 87 debug("Testing that component type framebuffer attachment queries are rejected with the extension disabled"); 88 const fbo = gl.createFramebuffer(); 89 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); 90 91 const rbo = gl.createRenderbuffer(); 92 gl.bindRenderbuffer(gl.RENDERBUFFER, rbo); 93 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,gl.RENDERBUFFER, rbo); 94 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGB565, 8, 8); 95 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setup renderbuffer should succeed."); 96 shouldBeNull('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, 0x8211 /* FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT */)'); 97 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Query must fail."); 98 gl.deleteRenderbuffer(rbo); 99 100 const tex = gl.createTexture(); 101 gl.bindTexture(gl.TEXTURE_2D, tex); 102 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0); 103 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 8, 8, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 104 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setup texture should succeed."); 105 shouldBeNull('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, 0x8211 /* FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT */)'); 106 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Query must fail."); 107 gl.deleteTexture(tex); 108 109 gl.deleteFramebuffer(fbo); 110 } 111 112 if (!gl.getExtension("OES_texture_float")) { 113 testPassed("No OES_texture_float support -- this is legal"); 114 } else { 115 testPassed("Successfully enabled OES_texture_float extension"); 116 // If alpha value is missing from a texture it gets filled to 1 when sampling according to GLES2.0 table 3.12 117 runTextureCreationTest(testProgram, true, gl.RGBA, 4, [10000, 10000, 10000, 10000]); 118 runTextureCreationTest(testProgram, true, gl.RGB, 3, [10000, 10000, 10000, 1]); 119 runTextureCreationTest(testProgram, true, gl.LUMINANCE, 1, [10000, 10000, 10000, 1]); 120 runTextureCreationTest(testProgram, true, gl.ALPHA, 1, [0, 0, 0, 10000]); 121 runTextureCreationTest(testProgram, true, gl.LUMINANCE_ALPHA, 2, [10000, 10000, 10000, 10000]); 122 123 (function() { 124 debug(""); 125 var renderable = isRenderable(gl); 126 var renderableExtName = "WEBGL_color_buffer_float"; 127 var supported = gl.getSupportedExtensions().includes(renderableExtName); 128 if (renderable && !supported) { 129 testFailed("RGBA/FLOAT is color renderable but " + renderableExtName + " not exposed"); 130 } else if (supported && !renderable) { 131 testFailed(renderableExtName + " is exposed but RGBA/FLOAT is not color renderable"); 132 } 133 if (supported) { 134 runRenderTargetAndReadbackTest(testProgram, gl.RGBA, 4, [10000, 10000, 10000, 10000], 0, true); 135 runRenderTargetAndReadbackTest(testProgram, gl.RGB, 3, [10000, 10000, 10000, 1], 0, false); 136 runRenderTargetAndReadbackTest(testProgram, gl.RGBA, 4, [10000, 10000, 10000, 10000], 1, true); 137 runRenderTargetAndReadbackTest(testProgram, gl.RGBA, 4, [10000, 10000, 10000, 10000], 0.5, true); 138 runFramebufferTest(); 139 140 { 141 debug(""); 142 debug("Testing that component type framebuffer attachment queries are accepted with the extension enabled"); 143 ext = gl.getExtension("WEBGL_color_buffer_float"); 144 shouldBeNonNull('ext'); 145 const fbo = gl.createFramebuffer(); 146 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); 147 148 const rbo = gl.createRenderbuffer(); 149 gl.bindRenderbuffer(gl.RENDERBUFFER, rbo); 150 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,gl.RENDERBUFFER, rbo); 151 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGB565, 8, 8); 152 shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT)', 'ext.UNSIGNED_NORMALIZED_EXT'); 153 gl.renderbufferStorage(gl.RENDERBUFFER, ext.RGBA32F_EXT, 8, 8); 154 shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT)', 'gl.FLOAT'); 155 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors after valid renderbuffer attachment queries."); 156 157 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT,gl.RENDERBUFFER, rbo); 158 gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, 8, 8); 159 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors after depth-stencil renderbuffer setup."); 160 shouldBeNull('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, ext.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT)'); 161 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Component type query is not allowed for combined depth-stencil attachments."); 162 gl.deleteRenderbuffer(rbo); 163 164 const tex = gl.createTexture(); 165 gl.bindTexture(gl.TEXTURE_2D, tex); 166 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0); 167 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 8, 8, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 168 shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT)', 'ext.UNSIGNED_NORMALIZED_EXT'); 169 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 8, 8, 0, gl.RGBA, gl.FLOAT, null); 170 shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT)', 'gl.FLOAT'); 171 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors after valid texture attachment queries."); 172 gl.deleteTexture(tex); 173 174 gl.deleteFramebuffer(fbo); 175 } 176 177 debug(""); 178 debug("Test float32 blending without EXT_float_blend."); 179 testExtFloatBlend(gl.RGBA); 180 181 debug(""); 182 debug("Testing that float32 blending succeeds with EXT_float_blend."); 183 if (!gl.getExtension("EXT_float_blend")) { 184 testPassed("No EXT_float_blend support -- this is legal"); 185 return; 186 } 187 testExtFloatBlend(gl.RGBA); 188 } 189 })(); 190 191 runUniqueObjectTest(); 192 } 193 } 194 195 function isRenderable(gl) { 196 var tex = gl.createTexture(); 197 gl.bindTexture(gl.TEXTURE_2D, tex); 198 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.FLOAT, null); 199 200 var fb = gl.createFramebuffer(); 201 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); 202 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0); 203 204 var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER); 205 gl.deleteFramebuffer(fb); 206 gl.deleteTexture(tex); 207 208 return status == gl.FRAMEBUFFER_COMPLETE; 209 } 210 211 function allocateTexture() 212 { 213 var texture = gl.createTexture(); 214 gl.bindTexture(gl.TEXTURE_2D, texture); 215 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 216 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 217 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 218 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 219 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texture parameter setup should succeed"); 220 return texture; 221 } 222 223 function checkRenderingResults() 224 { 225 wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green"); 226 } 227 228 function runTextureCreationTest(testProgram, extensionEnabled, opt_format, opt_numChannels, opt_subtractor) 229 { 230 var format = opt_format || gl.RGBA; 231 var numberOfChannels = opt_numChannels || 4; 232 var expectFailure = !extensionEnabled; 233 var subtractor = opt_subtractor || [10000, 10000, 10000, 10000]; 234 235 debug(""); 236 debug("testing format: " + wtu.glEnumToString(gl, format) + 237 " expect:" + (extensionEnabled ? "success" : "failure")); 238 239 var texture = allocateTexture(); 240 // Generate data. 241 var width = 2; 242 var height = 2; 243 var data = new Float32Array(width * height * numberOfChannels); 244 for (var ii = 0; ii < data.length; ++ii) { 245 data[ii] = 10000; 246 } 247 gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, format, gl.FLOAT, data); 248 if (expectFailure) { 249 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "floating-point texture allocation must be disallowed if OES_texture_float isn't enabled"); 250 return; 251 } else { 252 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "floating-point texture allocation should succeed if OES_texture_float is enabled"); 253 } 254 // Verify that the texture actually works for sampling and contains the expected data. 255 gl.uniform4fv(gl.getUniformLocation(testProgram, "subtractor"), subtractor); 256 wtu.clearAndDrawUnitQuad(gl); 257 checkRenderingResults(); 258 259 // Check that linear fails. 260 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); 261 wtu.clearAndDrawUnitQuad(gl); 262 wtu.checkCanvas(gl, [255, 0, 0, 255], "should be red"); 263 } 264 265 function arrayToString(arr, size) { 266 var mySize; 267 if (!size) 268 mySize = arr.length; 269 else 270 mySize = size; 271 var out = "["; 272 for (var ii = 0; ii < mySize; ++ii) { 273 if (ii > 0) { 274 out += ", "; 275 } 276 out += arr[ii]; 277 } 278 return out + "]"; 279 } 280 281 function runRenderTargetAndReadbackTest(testProgram, format, numberOfChannels, subtractor, texSubImageCover, requireRenderable) 282 { 283 var formatString = wtu.glEnumToString(gl, format); 284 debug(""); 285 debug("testing floating-point " + formatString + " render target" + (texSubImageCover > 0 ? " after calling texSubImage" : "")); 286 287 var texture = allocateTexture(); 288 var width = 2; 289 var height = 2; 290 gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, format, gl.FLOAT, null); 291 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "floating-point texture allocation should succeed if OES_texture_float is enabled"); 292 293 // Try to use this texture as a render target. 294 var fbo = gl.createFramebuffer(); 295 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); 296 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); 297 gl.bindTexture(gl.TEXTURE_2D, null); 298 // It is legal for a WebGL implementation exposing the OES_texture_float extension to 299 // support floating-point textures but not as attachments to framebuffer objects. 300 if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) { 301 if (requireRenderable) 302 testFailed("floating-point " + formatString + " render target not supported"); 303 else 304 debug("floating-point " + formatString + " render target not supported -- this is legal"); 305 return; 306 } 307 308 if (texSubImageCover > 0) { 309 // Ensure that replacing the whole texture or a part of it with texSubImage2D doesn't affect renderability 310 gl.bindTexture(gl.TEXTURE_2D, texture); 311 var data = new Float32Array(width * height * numberOfChannels * texSubImageCover); 312 gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height * texSubImageCover, format, gl.FLOAT, data); 313 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage2D should succeed if OES_texture_float is enabled"); 314 gl.bindTexture(gl.TEXTURE_2D, null); 315 if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) { 316 testFailed("render target support changed after calling texSubImage2D"); 317 return; 318 } 319 } 320 321 var renderProgram = 322 wtu.setupProgram(gl, 323 ["positionVertexShader", "floatingPointFragmentShader"], 324 ['vPosition'], 325 [0]); 326 wtu.clearAndDrawUnitQuad(gl); 327 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "rendering to floating-point texture should succeed"); 328 329 // Now sample from the floating-point texture and verify we got the correct values. 330 gl.bindFramebuffer(gl.FRAMEBUFFER, null); 331 gl.bindTexture(gl.TEXTURE_2D, texture); 332 gl.useProgram(testProgram); 333 gl.uniform1i(gl.getUniformLocation(testProgram, "tex"), 0); 334 gl.uniform4fv(gl.getUniformLocation(testProgram, "subtractor"), subtractor); 335 wtu.clearAndDrawUnitQuad(gl); 336 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "rendering from floating-point texture should succeed"); 337 checkRenderingResults(); 338 339 // Finally, if the implementation supports floating-point readback, verify it. 340 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); 341 var implFormat = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_FORMAT); 342 var implType = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_TYPE); 343 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "getParameter of IMPLEMENTATION_COLOR_READ_{FORMAT|TYPE} should succeed"); 344 if ((implFormat == gl.RGBA || implFormat == gl.RGB) && implType == gl.FLOAT) { 345 debug("Checking readback of floating-point values"); 346 var arraySize = (implFormat == gl.RGBA) ? 4 : 3 347 var buf = new Float32Array(arraySize); 348 gl.readPixels(0, 0, 1, 1, implFormat, implType , buf); 349 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "readPixels from floating-point renderbuffer should succeed"); 350 var ok = true; 351 var tolerance = 8.0; // TODO: factor this out from both this test and the subtractor shader above. 352 for (var ii = 0; ii < buf.length; ++ii) { 353 if (Math.abs(buf[ii] - subtractor[ii]) > tolerance) { 354 ok = false; 355 break; 356 } 357 } 358 if (ok) { 359 testPassed("readPixels of float-type data from floating-point renderbuffer succeeded"); 360 } else { 361 testFailed("readPixels of float-type data from floating-point renderbuffer failed: expected " 362 + arrayToString(subtractor, arraySize) + ", got " + arrayToString(buf)); 363 } 364 } 365 } 366 367 function runUniqueObjectTest() 368 { 369 debug(""); 370 debug("Testing that getExtension() returns the same object each time"); 371 gl.getExtension("OES_texture_float").myProperty = 2; 372 webglHarnessCollectGarbage(); 373 shouldBe('gl.getExtension("OES_texture_float").myProperty', '2'); 374 } 375 376 // Make sure we can call readPixels with the passed in arrayBufferConstructor and that the color 377 // channels are the ones we expect. If there is a mismatch between the glType and arrayBuffer type, 378 // fail the test. 379 function verifyReadPixelsColors(red, green, blue, alpha, alphaRGB, glFormat, glType, arrayBufferConstructor) { 380 var typeName = wtu.glEnumToString(gl, glType); 381 382 debug(wtu.glEnumToString(gl, glFormat) + " framebuffer with " + typeName + " readback."); 383 384 var arrayBuffer = new arrayBufferConstructor(4); 385 gl.readPixels(0, 0, 1, 1, gl.RGBA, glType, arrayBuffer); 386 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "readPixels should return NO_ERROR when reading " + typeName + " data."); 387 388 assertMsg(arrayBuffer[0] === red, "Red channel should be " + red + " for " + typeName + " readPixels. Received: " + arrayBuffer[0]); 389 assertMsg(arrayBuffer[1] === green, "Green channel should be " + green + " for " + typeName + " readPixels. Received: " + arrayBuffer[1]); 390 assertMsg(arrayBuffer[2] === blue, "Blue channel should be " + blue + " for " + typeName + " readPixels. Received: " + arrayBuffer[2]); 391 if (glFormat === gl.RGBA) { 392 assertMsg(arrayBuffer[3] === alpha, "Alpha channel should be " + alpha + " for " + typeName + " readPixels. Received: " + arrayBuffer[3]); 393 } else if (glFormat === gl.RGB) { 394 assertMsg(arrayBuffer[3] === alphaRGB, "Alpha channel should be " + alphaRGB + " for " + typeName + " readPixels. Received: " + arrayBuffer[3]); 395 } 396 397 // Make sure any arrayBuffer types that are not equal to arrayBufferConstructor fail readPixels. 398 if (arrayBufferConstructor !== Uint8Array) { 399 arrayBuffer = new Uint8Array(4); 400 gl.readPixels(0, 0, 1, 1, gl.RGBA, glType, arrayBuffer); 401 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "readPixels should return INVALID_OPERATION when reading mismatched types. " + Uint8Array.toString()); 402 } 403 if (arrayBufferConstructor !== Float32Array) { 404 arrayBuffer = new Float32Array(4); 405 gl.readPixels(0, 0, 1, 1, gl.RGBA, glType, arrayBuffer); 406 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "readPixels should return INVALID_OPERATION when reading mismatched types. " + Float32Array.toString()); 407 } 408 if (arrayBufferConstructor !== Uint16Array) { 409 arrayBuffer = new Uint16Array(4); 410 gl.readPixels(0, 0, 1, 1, gl.RGBA, glType, arrayBuffer); 411 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "readPixels should return INVALID_OPERATION when reading mismatched types. " + Uint16Array.toString()); 412 } 413 } 414 415 // Verify that float textures attached to frame buffers function correctly with regard to framebuffer 416 // completness, IMPLEMENTATION_COLOR_READ_FORMAT/TYPE and readPixels 417 function runFramebufferTest() { 418 debug(""); 419 debug("Framebuffer Tests"); 420 421 var texture = allocateTexture(); 422 gl.bindTexture(gl.TEXTURE_2D, texture); 423 424 var fbo = gl.createFramebuffer(); 425 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); 426 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); 427 428 debug("Ensure non-color-renderable formats [LUMINANCE, LUMINANCE_ALPHA, ALPHA] fail."); 429 var arrayBufferFloatOutput = new Float32Array(4); // 4 color channels 430 [gl.LUMINANCE, gl.LUMINANCE_ALPHA, gl.ALPHA].forEach(function(badFormat) { 431 debug(wtu.glEnumToString(gl, badFormat) + " framebuffer"); 432 433 gl.texImage2D(gl.TEXTURE_2D, 0, badFormat, 1, 1, 0, badFormat, gl.FLOAT, null); 434 shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT"); 435 436 shouldBeNull("gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_FORMAT)"); 437 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "IMPLEMENTATION_COLOR_READ_FORMAT should fail for incomplete framebuffers."); 438 439 shouldBeNull("gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_TYPE)"); 440 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "IMPLEMENTATION_COLOR_READ_TYPE should fail for incomplete framebuffers."); 441 442 gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.FLOAT, arrayBufferFloatOutput); 443 wtu.glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION , "readPixels should fail on incomplete framebuffers."); 444 debug(""); 445 }); 446 447 debug("Ensure color renderable formats [RGBA, RGB] succeed."); 448 var arrayBufferFloatInput = new Float32Array(4); // 4 color channels 449 arrayBufferFloatInput[0] = 0; 450 arrayBufferFloatInput[1] = .25; 451 arrayBufferFloatInput[2] = .50; 452 arrayBufferFloatInput[3] = .75; 453 454 [gl.RGBA, gl.RGB].forEach(function(goodFormat) { 455 debug(""); 456 debug(wtu.glEnumToString(gl, goodFormat) + " framebuffer tests"); 457 458 gl.texImage2D(gl.TEXTURE_2D, 0, goodFormat, 1, 1, 0, goodFormat, gl.FLOAT, arrayBufferFloatInput); 459 if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) { 460 testPassed("Format is not renderable. This is allowed."); 461 return; 462 } 463 verifyReadPixelsColors( 464 0.00, // red 465 0.25, // green 466 0.50, // blue 467 0.75, // alpha 468 1.0, // alphaRGB 469 goodFormat, 470 gl.FLOAT, 471 Float32Array); 472 473 var implementationColorReadFormat = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_FORMAT); 474 assertMsg(implementationColorReadFormat === gl.RGBA || implementationColorReadFormat === gl.RGB, 475 "IMPLEMENTATION_COLOR_READ_FORMAT should be color renderable: RGBA or RGB. Received: " + wtu.glEnumToString(gl, implementationColorReadFormat)); 476 477 var implementationColorReadType = gl.getParameter(gl.IMPLEMENTATION_COLOR_READ_TYPE); 478 assertMsg(implementationColorReadType === gl.UNSIGNED_BYTE || 479 implementationColorReadType === gl.FLOAT || 480 "IMPLEMENTATION_COLOR_READ_TYPE must be one of UNSIGNED_BYTE or FLOAT " + 481 "Received: " + wtu.glEnumToString(gl, implementationColorReadType)); 482 }); 483 } 484 485 debug(""); 486 var successfullyParsed = true; 487 </script> 488 <script src="../../js/js-test-post.js"></script> 489 490 </body> 491 </html>