OLD | NEW |
(Empty) | |
| 1 <!-- |
| 2 |
| 3 /* |
| 4 ** Copyright (c) 2013 The Khronos Group Inc. |
| 5 ** |
| 6 ** Permission is hereby granted, free of charge, to any person obtaining a |
| 7 ** copy of this software and/or associated documentation files (the |
| 8 ** "Materials"), to deal in the Materials without restriction, including |
| 9 ** without limitation the rights to use, copy, modify, merge, publish, |
| 10 ** distribute, sublicense, and/or sell copies of the Materials, and to |
| 11 ** permit persons to whom the Materials are furnished to do so, subject to |
| 12 ** the following conditions: |
| 13 ** |
| 14 ** The above copyright notice and this permission notice shall be included |
| 15 ** in all copies or substantial portions of the Materials. |
| 16 ** |
| 17 ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 18 ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 19 ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
| 20 ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
| 21 ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
| 22 ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
| 23 ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. |
| 24 */ |
| 25 |
| 26 --> |
| 27 |
| 28 <!DOCTYPE html> |
| 29 <html> |
| 30 <head> |
| 31 <meta charset="utf-8"> |
| 32 <title>WebGL WEBGL_draw_buffers Conformance Tests</title> |
| 33 <link rel="stylesheet" href="../../resources/js-test-style.css"/> |
| 34 <script src="../../resources/desktop-gl-constants.js" type="text/javascript"></s
cript> |
| 35 <script src="../../resources/js-test-pre.js"></script> |
| 36 <script src="../resources/webgl-test.js"></script> |
| 37 <script src="../resources/webgl-test-utils.js"></script> |
| 38 </head> |
| 39 <body> |
| 40 <div id="description"></div> |
| 41 <canvas id="canvas" width="64" height="64"> </canvas> |
| 42 <div id="console"></div> |
| 43 <script id="vshader" type="x-shader/x-vertex"> |
| 44 attribute vec4 a_position; |
| 45 void main() { |
| 46 gl_Position = a_position; |
| 47 } |
| 48 </script> |
| 49 <script id="fshader" type="x-shader/x-fragment"> |
| 50 #extension GL_EXT_draw_buffers : require |
| 51 precision mediump float; |
| 52 uniform vec4 u_colors[$(numDrawingBuffers)]; |
| 53 void main() { |
| 54 for (int i = 0; i < $(numDrawingBuffers); ++i) { |
| 55 gl_FragData[i] = u_colors[i]; |
| 56 } |
| 57 } |
| 58 </script> |
| 59 <script id="fshaderRed" type="x-shader/x-fragment"> |
| 60 precision mediump float; |
| 61 void main() { |
| 62 gl_FragColor = vec4(1,0,0,1); |
| 63 } |
| 64 </script> |
| 65 <script id="fshaderMacroDisabled" type="x-shader/x-fragment"> |
| 66 #ifdef GL_EXT_draw_buffers |
| 67 bad code here |
| 68 #endif |
| 69 precision mediump float; |
| 70 void main() { |
| 71 gl_FragColor = vec4(0,0,0,0); |
| 72 } |
| 73 </script> |
| 74 <script id="fshaderMacroEnabled" type="x-shader/x-fragment"> |
| 75 #ifdef GL_EXT_draw_buffers |
| 76 #if GL_EXT_draw_buffers == 1 |
| 77 #define CODE |
| 78 #else |
| 79 #define CODE this_code_is_bad_it_should_have_compiled |
| 80 #endif |
| 81 #else |
| 82 #define CODE this_code_is_bad_it_should_have_compiled |
| 83 #endif |
| 84 CODE |
| 85 precision mediump float; |
| 86 void main() { |
| 87 gl_FragColor = vec4(0,0,0,0); |
| 88 } |
| 89 </script> |
| 90 <script id="fshaderBuiltInConstEnabled" type="x-shader/x-fragment"> |
| 91 precision mediump float; |
| 92 void main() { |
| 93 gl_FragColor = (gl_MaxDrawBuffers == $(numDrawingBuffers)) ? vec4(0,1,0,1) :
vec4(1,0,0,1); |
| 94 } |
| 95 </script> |
| 96 <script> |
| 97 "use strict"; |
| 98 description("This test verifies the functionality of the WEBGL_draw_buffers exte
nsion, if it is available."); |
| 99 |
| 100 debug(""); |
| 101 |
| 102 var wtu = WebGLTestUtils; |
| 103 var canvas = document.getElementById("canvas"); |
| 104 var output = document.getElementById("console"); |
| 105 var gl = wtu.create3DContext(canvas); |
| 106 var ext = null; |
| 107 var vao = null; |
| 108 |
| 109 var extensionConstants = [ |
| 110 { name: "MAX_COLOR_ATTACHMENTS_WEBGL", enum: 0x8CDF, expectedFn: function(v) {
return v > 0; }, passMsg: " should be > 0"}, |
| 111 { name: "MAX_DRAW_BUFFERS_WEBGL", enum: 0x8824, expectedFn: function(v) {
return v > 0; }, passMsg: " should be > 0"}, |
| 112 |
| 113 { name: "COLOR_ATTACHMENT0_WEBGL", enum: 0x8CE0, }, |
| 114 { name: "COLOR_ATTACHMENT1_WEBGL", enum: 0x8CE1, }, |
| 115 { name: "COLOR_ATTACHMENT2_WEBGL", enum: 0x8CE2, }, |
| 116 { name: "COLOR_ATTACHMENT3_WEBGL", enum: 0x8CE3, }, |
| 117 { name: "COLOR_ATTACHMENT4_WEBGL", enum: 0x8CE4, }, |
| 118 { name: "COLOR_ATTACHMENT5_WEBGL", enum: 0x8CE5, }, |
| 119 { name: "COLOR_ATTACHMENT6_WEBGL", enum: 0x8CE6, }, |
| 120 { name: "COLOR_ATTACHMENT7_WEBGL", enum: 0x8CE7, }, |
| 121 { name: "COLOR_ATTACHMENT8_WEBGL", enum: 0x8CE8, }, |
| 122 { name: "COLOR_ATTACHMENT9_WEBGL", enum: 0x8CE9, }, |
| 123 { name: "COLOR_ATTACHMENT10_WEBGL", enum: 0x8CEA, }, |
| 124 { name: "COLOR_ATTACHMENT11_WEBGL", enum: 0x8CEB, }, |
| 125 { name: "COLOR_ATTACHMENT12_WEBGL", enum: 0x8CEC, }, |
| 126 { name: "COLOR_ATTACHMENT13_WEBGL", enum: 0x8CED, }, |
| 127 { name: "COLOR_ATTACHMENT14_WEBGL", enum: 0x8CEE, }, |
| 128 { name: "COLOR_ATTACHMENT15_WEBGL", enum: 0x8CEF, }, |
| 129 |
| 130 { name: "DRAW_BUFFER0_WEBGL", enum: 0x8825, }, |
| 131 { name: "DRAW_BUFFER1_WEBGL", enum: 0x8826, }, |
| 132 { name: "DRAW_BUFFER2_WEBGL", enum: 0x8827, }, |
| 133 { name: "DRAW_BUFFER3_WEBGL", enum: 0x8828, }, |
| 134 { name: "DRAW_BUFFER4_WEBGL", enum: 0x8829, }, |
| 135 { name: "DRAW_BUFFER5_WEBGL", enum: 0x882A, }, |
| 136 { name: "DRAW_BUFFER6_WEBGL", enum: 0x882B, }, |
| 137 { name: "DRAW_BUFFER7_WEBGL", enum: 0x882C, }, |
| 138 { name: "DRAW_BUFFER8_WEBGL", enum: 0x882D, }, |
| 139 { name: "DRAW_BUFFER9_WEBGL", enum: 0x882E, }, |
| 140 { name: "DRAW_BUFFER10_WEBGL", enum: 0x882F, }, |
| 141 { name: "DRAW_BUFFER11_WEBGL", enum: 0x8830, }, |
| 142 { name: "DRAW_BUFFER12_WEBGL", enum: 0x8831, }, |
| 143 { name: "DRAW_BUFFER13_WEBGL", enum: 0x8832, }, |
| 144 { name: "DRAW_BUFFER14_WEBGL", enum: 0x8833, }, |
| 145 { name: "DRAW_BUFFER15_WEBGL", enum: 0x8834, }, |
| 146 ]; |
| 147 |
| 148 if (!gl) { |
| 149 testFailed("WebGL context does not exist"); |
| 150 } else { |
| 151 testPassed("WebGL context exists"); |
| 152 |
| 153 // Run tests with extension disabled |
| 154 runEnumTestDisabled(); |
| 155 runShadersTestDisabled(); |
| 156 runAttachmentTestDisabled(); |
| 157 |
| 158 debug(""); |
| 159 |
| 160 // Query the extension and store globally so shouldBe can access it |
| 161 ext = gl.getExtension("WEBGL_draw_buffers"); |
| 162 if (!ext) { |
| 163 testPassed("No WEBGL_draw_buffers support -- this is legal"); |
| 164 |
| 165 runSupportedTest(false); |
| 166 } else { |
| 167 testPassed("Successfully enabled WEBGL_draw_buffers extension"); |
| 168 |
| 169 runSupportedTest(true); |
| 170 runEnumTestEnabled(); |
| 171 runShadersTestEnabled(); |
| 172 runAttachmentTestEnabled(); |
| 173 runDrawTests(); |
| 174 |
| 175 glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors"); |
| 176 } |
| 177 } |
| 178 |
| 179 function createExtDrawBuffersProgram(scriptId, sub) { |
| 180 var fsource = wtu.getScript(scriptId); |
| 181 fsource = wtu.replaceParams(fsource, sub); |
| 182 wtu.addShaderSource(output, "fragement shader", fsource); |
| 183 return wtu.setupProgram(gl, ["vshader", fsource], ["a_position"]); |
| 184 } |
| 185 |
| 186 function runSupportedTest(extensionEnabled) { |
| 187 var supported = gl.getSupportedExtensions(); |
| 188 if (supported.indexOf("WEBGL_draw_buffers") >= 0) { |
| 189 if (extensionEnabled) { |
| 190 testPassed("WEBGL_draw_buffers listed as supported and getExtension succee
ded"); |
| 191 } else { |
| 192 testFailed("WEBGL_draw_buffers listed as supported but getExtension failed
"); |
| 193 } |
| 194 } else { |
| 195 if (extensionEnabled) { |
| 196 testFailed("WEBGL_draw_buffers not listed as supported but getExtension su
cceeded"); |
| 197 } else { |
| 198 testPassed("WEBGL_draw_buffers not listed as supported and getExtension fa
iled -- this is legal"); |
| 199 } |
| 200 } |
| 201 } |
| 202 |
| 203 function runEnumTestDisabled() { |
| 204 debug(""); |
| 205 debug("Testing binding enum with extension disabled"); |
| 206 |
| 207 // Use the constant directly as we don't have the extension |
| 208 extensionConstants.forEach(function(c) { |
| 209 if (c.expectedFn) { |
| 210 gl.getParameter(c.enum); |
| 211 glErrorShouldBe(gl, gl.INVALID_ENUM, c.name + " should not be queryable if
extension is disabled"); |
| 212 } |
| 213 }); |
| 214 glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors"); |
| 215 } |
| 216 |
| 217 function runEnumTestEnabled() { |
| 218 debug(""); |
| 219 debug("Testing enums with extension enabled"); |
| 220 |
| 221 extensionConstants.forEach(function(c) { |
| 222 shouldBe("ext." + c.name, "0x" + c.enum.toString(16)); |
| 223 if (c.expectedFn) { |
| 224 glErrorShouldBe(gl, gl.NO_ERROR, "foo"); |
| 225 debug(c.name + ":" + ext[c.name].toString(16)); |
| 226 expectTrue(c.expectedFn(gl.getParameter(ext[c.name])), "gl.getParemter(ext
." + c.name + ")" + c.passMsg); |
| 227 glErrorShouldBe(gl, gl.NO_ERROR, c.name + " query should succeed if extens
ion is enabled"); |
| 228 } |
| 229 }); |
| 230 |
| 231 debug("Testing drawBuffersWEBGL with default drawing buffer"); |
| 232 shouldBe("gl.getParameter(ext.DRAW_BUFFER0_WEBGL)", "gl.BACK"); |
| 233 shouldGenerateGLError(gl, gl.INVALID_VALUE, "ext.drawBuffersWEBGL([])"); |
| 234 shouldGenerateGLError(gl, gl.INVALID_VALUE, "ext.drawBuffersWEBGL([gl.NONE, gl
.NONE])"); |
| 235 shouldGenerateGLError(gl, gl.INVALID_OPERATION, "ext.drawBuffersWEBGL([ext.COL
OR_ATTACHMENT0_WEBGL])"); |
| 236 shouldBe("gl.getParameter(ext.DRAW_BUFFER0_WEBGL)", "gl.BACK"); |
| 237 shouldGenerateGLError(gl, gl.NO_ERROR, "ext.drawBuffersWEBGL([gl.NONE])"); |
| 238 shouldBe("gl.getParameter(ext.DRAW_BUFFER0_WEBGL)", "gl.NONE"); |
| 239 shouldGenerateGLError(gl, gl.NO_ERROR, "ext.drawBuffersWEBGL([gl.BACK])"); |
| 240 shouldBe("gl.getParameter(ext.DRAW_BUFFER0_WEBGL)", "gl.BACK"); |
| 241 glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors"); |
| 242 } |
| 243 |
| 244 function testShaders(tests, sub) { |
| 245 tests.forEach(function(test) { |
| 246 var shaders = [wtu.getScript(test.shaders[0]), wtu.replaceParams(wtu.getScri
pt(test.shaders[1]), sub)]; |
| 247 wtu.addShaderSource(output, "vertex shader", shaders[0]); |
| 248 wtu.addShaderSource(output, "fragement shader", shaders[1]); |
| 249 var program = wtu.setupProgram(gl, shaders, ["a_position"]); |
| 250 var programLinkedSuccessfully = (program != null); |
| 251 var expectedProgramToLinkSuccessfully = (test.expectFailure == true); |
| 252 expectTrue(programLinkedSuccessfully != expectedProgramToLinkSuccessfully, t
est.msg); |
| 253 gl.deleteProgram(program); |
| 254 }); |
| 255 } |
| 256 |
| 257 function runShadersTestDisabled() { |
| 258 debug(""); |
| 259 debug("test shaders disabled"); |
| 260 |
| 261 testShaders([ |
| 262 { shaders: ["vshader", "fshaderMacroDisabled"], |
| 263 msg: "GL_EXT_draw_buffers should not be defined in GLSL", |
| 264 }, |
| 265 { shaders: ["vshader", "fshader"], |
| 266 msg: "#extension GL_EXT_draw_buffers should not be allowed in GLSL", |
| 267 expectFailure: true, |
| 268 }, |
| 269 ], {numDrawingBuffers: 1}); |
| 270 glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors"); |
| 271 } |
| 272 |
| 273 function runShadersTestEnabled() { |
| 274 debug(""); |
| 275 debug("test shaders enabled"); |
| 276 |
| 277 var sub = {numDrawingBuffers: gl.getParameter(ext.MAX_DRAW_BUFFERS_WEBGL)}; |
| 278 testShaders([ |
| 279 { shaders: ["vshader", "fshaderMacroEnabled"], |
| 280 msg: "GL_EXT_draw_buffers should be defined as 1 in GLSL", |
| 281 }, |
| 282 ], sub); |
| 283 |
| 284 var program = createExtDrawBuffersProgram("fshaderBuiltInConstEnabled", sub); |
| 285 wtu.setupUnitQuad(gl); |
| 286 wtu.clearAndDrawUnitQuad(gl); |
| 287 wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green"); |
| 288 gl.deleteProgram(program); |
| 289 glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors"); |
| 290 } |
| 291 |
| 292 function runAttachmentTestDisabled() { |
| 293 debug(""); |
| 294 debug("test attachment disabled"); |
| 295 var tex = gl.createTexture(); |
| 296 var fb = gl.createFramebuffer(); |
| 297 gl.bindTexture(gl.TEXTURE_2D, tex); |
| 298 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); |
| 299 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + 1, gl.TEXTURE_2
D, tex, 0); |
| 300 glErrorShouldBe(gl, gl.INVALID_ENUM, "should not be able to attach to gl.COLOR
_ATTACHMENT1"); |
| 301 gl.deleteFramebuffer(fb); |
| 302 gl.deleteTexture(tex); |
| 303 glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors"); |
| 304 } |
| 305 |
| 306 function makeArray(size, value) { |
| 307 var array = [] |
| 308 for (var ii = 0; ii < size; ++ii) { |
| 309 array.push(value); |
| 310 } |
| 311 return array; |
| 312 } |
| 313 |
| 314 function makeColorAttachmentArray(size) { |
| 315 var array = [] |
| 316 for (var ii = 0; ii < size; ++ii) { |
| 317 array.push(gl.COLOR_ATTACHMENT0 + ii); |
| 318 } |
| 319 return array; |
| 320 } |
| 321 |
| 322 function runAttachmentTestEnabled() { |
| 323 debug(""); |
| 324 debug("test attachment enabled"); |
| 325 |
| 326 var maxDrawingBuffers = gl.getParameter(ext.MAX_DRAW_BUFFERS_WEBGL); |
| 327 var maxColorAttachments = gl.getParameter(ext.MAX_COLOR_ATTACHMENTS_WEBGL); |
| 328 |
| 329 var tex = gl.createTexture(); |
| 330 var fb = gl.createFramebuffer(); |
| 331 gl.bindTexture(gl.TEXTURE_2D, tex); |
| 332 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); |
| 333 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + maxColorAttachm
ents, gl.TEXTURE_2D, tex, 0); |
| 334 glErrorShouldBe(gl, gl.INVALID_ENUM, "should not be able to attach pass the ma
x attachment point: gl.COLOR_ATTACHMENT0 + " + maxColorAttachments); |
| 335 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + maxColorAttachm
ents - 1, gl.TEXTURE_2D, tex, 0); |
| 336 glErrorShouldBe(gl, gl.NO_ERROR, "should be able to attach to the max attachme
nt point: gl.COLOR_ATTACHMENT0 + " + (maxColorAttachments - 1)); |
| 337 ext.drawBuffersWEBGL(makeArray(maxDrawingBuffers, gl.NONE)); |
| 338 glErrorShouldBe(gl, gl.NO_ERROR, "should be able to call drawBuffersWEBGL with
array NONE of size " + maxColorAttachments); |
| 339 var bufs = makeColorAttachmentArray(maxDrawingBuffers); |
| 340 ext.drawBuffersWEBGL(bufs); |
| 341 glErrorShouldBe(gl, gl.NO_ERROR, "should be able to call drawBuffersWEBGL with
array attachments of size " + maxColorAttachments); |
| 342 bufs[0] = gl.NONE; |
| 343 ext.drawBuffersWEBGL(bufs); |
| 344 glErrorShouldBe(gl, gl.NO_ERROR, "should be able to call drawBuffersWEBGL with
mixed array attachments of size " + maxColorAttachments); |
| 345 if (maxDrawingBuffers > 1) { |
| 346 bufs[0] = ext.COLOR_ATTACHMENT1_WEBGL; |
| 347 bufs[1] = ext.COLOR_ATTACHMENT0_WEBGL; |
| 348 ext.drawBuffersWEBGL(bufs); |
| 349 glErrorShouldBe(gl, gl.INVALID_OPERATION, "should not be able to call drawBu
ffersWEBGL with out of order attachments of size " + maxColorAttachments); |
| 350 var bufs = makeColorAttachmentArray(Math.floor(maxDrawingBuffers / 2)); |
| 351 glErrorShouldBe(gl, gl.NO_ERROR, "should not be able to call drawBuffersWEBG
L with short array of attachments of size " + maxColorAttachments); |
| 352 } |
| 353 |
| 354 gl.deleteFramebuffer(fb); |
| 355 gl.deleteTexture(tex); |
| 356 glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors"); |
| 357 } |
| 358 |
| 359 function makeColorByIndex(index) { |
| 360 var low = (index - 1) % 15 + 1; |
| 361 var high = (index - 1) / 15; |
| 362 |
| 363 var zeroOrOne = function(v) { |
| 364 return v ? 1 : 0; |
| 365 }; |
| 366 |
| 367 var oneOrTwo = function(v) { |
| 368 return v ? 2 : 1; |
| 369 } |
| 370 |
| 371 var makeComponent = function(b0, b1, b2) { |
| 372 return Math.floor(255 * zeroOrOne(b0) / oneOrTwo(b1) / oneOrTwo(b2)); |
| 373 }; |
| 374 return [ |
| 375 makeComponent(low & (1 << 0), high & (1 << 0), high & (1 << 4)), |
| 376 makeComponent(low & (1 << 1), high & (1 << 1), high & (1 << 5)), |
| 377 makeComponent(low & (1 << 2), high & (1 << 2), high & (1 << 6)), |
| 378 makeComponent(low & (1 << 3), high & (1 << 3), high & (1 << 7)), |
| 379 ]; |
| 380 } |
| 381 |
| 382 function runDrawTests() { |
| 383 debug(""); |
| 384 debug("--------- draw tests -----------"); |
| 385 var fb = gl.createFramebuffer(); |
| 386 var fb2 = gl.createFramebuffer(); |
| 387 var halfFB1 = gl.createFramebuffer(); |
| 388 var halfFB2 = gl.createFramebuffer(); |
| 389 var endsFB = gl.createFramebuffer(); |
| 390 var middleFB = gl.createFramebuffer(); |
| 391 |
| 392 var maxDrawingBuffers = gl.getParameter(ext.MAX_DRAW_BUFFERS_WEBGL); |
| 393 var maxColorAttachments = gl.getParameter(ext.MAX_COLOR_ATTACHMENTS_WEBGL); |
| 394 var maxUniformVectors = gl.getParameter(gl.MAX_FRAGMENT_UNIFORM_VECTORS); |
| 395 var maxUsable = Math.min(maxDrawingBuffers, maxColorAttachments, maxUniformVec
tors); |
| 396 var half = Math.floor(maxUsable / 2); |
| 397 var bufs = makeColorAttachmentArray(maxUsable); |
| 398 var nones = makeArray(maxUsable, gl.NONE); |
| 399 |
| 400 [fb, fb2, halfFB1, halfFB2, endsFB, middleFB].forEach(function(fbo) { |
| 401 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); |
| 402 ext.drawBuffersWEBGL(bufs); |
| 403 }); |
| 404 |
| 405 var checkProgram = wtu.setupTexturedQuad(gl); |
| 406 var redProgram = wtu.setupProgram(gl, ["vshader", "fshaderRed"], ["a_position"
]); |
| 407 var drawProgram = createExtDrawBuffersProgram("fshader", {numDrawingBuffers: m
axDrawingBuffers}); |
| 408 var width = 64; |
| 409 var height = 64; |
| 410 var attachments = []; |
| 411 // Makes 6 framebuffers. |
| 412 // fb and fb2 have all the attachments. |
| 413 // halfFB1 has the first half of the attachments |
| 414 // halfFB2 has the second half of the attachments |
| 415 // endsFB has the first and last attachments |
| 416 // middleFB has all but the first and last attachments |
| 417 for (var ii = 0; ii < maxUsable; ++ii) { |
| 418 var tex = gl.createTexture(); |
| 419 gl.bindTexture(gl.TEXTURE_2D, tex); |
| 420 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIG
NED_BYTE, null); |
| 421 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); |
| 422 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); |
| 423 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); |
| 424 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); |
| 425 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); |
| 426 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ii, gl.TEXTUR
E_2D, tex, 0); |
| 427 gl.bindFramebuffer(gl.FRAMEBUFFER, fb2); |
| 428 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ii, gl.TEXTUR
E_2D, tex, 0); |
| 429 gl.bindFramebuffer(gl.FRAMEBUFFER, ii < half ? halfFB1 : halfFB2); |
| 430 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ii, gl.TEXTUR
E_2D, tex, 0); |
| 431 gl.bindFramebuffer(gl.FRAMEBUFFER, (ii == 0 || ii == (maxUsable - 1)) ? ends
FB : middleFB); |
| 432 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ii, gl.TEXTUR
E_2D, tex, 0); |
| 433 var location = gl.getUniformLocation(drawProgram, "u_colors[" + ii + "]"); |
| 434 var color = makeColorByIndex(ii + 1); |
| 435 var floatColor = [color[0] / 255, color[1] / 255, color[2] / 255, color[3] /
255]; |
| 436 gl.uniform4fv(location, floatColor); |
| 437 attachments.push({ |
| 438 texture: tex, |
| 439 location: location, |
| 440 color: color |
| 441 }); |
| 442 } |
| 443 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); |
| 444 shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE
"); |
| 445 gl.bindFramebuffer(gl.FRAMEBUFFER, fb2); |
| 446 shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE
"); |
| 447 |
| 448 var checkAttachmentsForColorFn = function(attachments, colorFn) { |
| 449 gl.bindFramebuffer(gl.FRAMEBUFFER, null); |
| 450 gl.useProgram(checkProgram); |
| 451 attachments.forEach(function(attachment, index) { |
| 452 gl.bindTexture(gl.TEXTURE_2D, attachment.texture); |
| 453 wtu.clearAndDrawUnitQuad(gl); |
| 454 var expectedColor = colorFn(attachment, index); |
| 455 var tolerance = 0; |
| 456 expectedColor.forEach(function(v) { |
| 457 if (v != 0 && v != 255) { |
| 458 tolerance = 8; |
| 459 } |
| 460 }); |
| 461 wtu.checkCanvas(gl, expectedColor, "attachment " + index + " should be " +
expectedColor.toString(), tolerance); |
| 462 }); |
| 463 debug(""); |
| 464 }; |
| 465 |
| 466 var checkAttachmentsForColor = function(attachments, color) { |
| 467 checkAttachmentsForColorFn(attachments, function(attachment, index) { |
| 468 return color || attachment.color; |
| 469 }); |
| 470 }; |
| 471 |
| 472 var drawAndCheckAttachments = function(testFB, msg, testFn) { |
| 473 debug("test clearing " + msg); |
| 474 |
| 475 gl.bindFramebuffer(gl.FRAMEBUFFER, testFB); |
| 476 |
| 477 attachments.forEach(function(attachment, index) { |
| 478 debug("attachment: " + index + " = " + wtu.glEnumToString(gl, gl.getParame
ter(ext.DRAW_BUFFER0_WEBGL + index)) + |
| 479 ", " + wtu.glEnumToString(gl, gl.getFramebufferAttachmentParameter(g
l.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + index, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TY
PE))); |
| 480 }); |
| 481 |
| 482 if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) { |
| 483 debug("framebuffer not complete"); |
| 484 debug(""); |
| 485 return; |
| 486 } |
| 487 |
| 488 // Clear all the attachments |
| 489 gl.bindFramebuffer(gl.FRAMEBUFFER, fb2); |
| 490 gl.clearColor(0, 0, 0, 0); |
| 491 gl.clear(gl.COLOR_BUFFER_BIT); |
| 492 //checkAttachmentsForColorFn(attachments, function(attachment, index) { |
| 493 // return [0, 0, 0, 0]; |
| 494 //}); |
| 495 //debug("--"); |
| 496 |
| 497 // Clear some attachments using testFB |
| 498 gl.bindFramebuffer(gl.FRAMEBUFFER, testFB); |
| 499 |
| 500 gl.clearColor(0, 1, 0, 1); |
| 501 gl.clear(gl.COLOR_BUFFER_BIT); |
| 502 checkAttachmentsForColorFn(attachments, function(attachment, index) { |
| 503 return testFn(attachment, index) ? [0, 255, 0, 255] : [0, 0, 0, 0]; |
| 504 }); |
| 505 |
| 506 debug("test drawing to " + msg); |
| 507 |
| 508 // Draw to some attachments using testFB |
| 509 gl.useProgram(drawProgram); |
| 510 gl.bindFramebuffer(gl.FRAMEBUFFER, testFB); |
| 511 wtu.drawUnitQuad(gl); |
| 512 |
| 513 checkAttachmentsForColorFn(attachments, function(attachment, index) { |
| 514 return testFn(attachment, index) ? attachment.color : [0, 0, 0, 0]; |
| 515 }); |
| 516 }; |
| 517 |
| 518 gl.useProgram(drawProgram); |
| 519 gl.bindFramebuffer(gl.FRAMEBUFFER, fb2); |
| 520 ext.drawBuffersWEBGL(bufs); |
| 521 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); |
| 522 ext.drawBuffersWEBGL(bufs); |
| 523 |
| 524 wtu.drawUnitQuad(gl); |
| 525 |
| 526 debug("test that each texture got the correct color."); |
| 527 |
| 528 checkAttachmentsForColor(attachments); |
| 529 |
| 530 debug("test clearing clears all the textures"); |
| 531 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); |
| 532 gl.clearColor(0, 1, 0, 1); |
| 533 gl.clear(gl.COLOR_BUFFER_BIT); |
| 534 |
| 535 checkAttachmentsForColor(attachments, [0, 255, 0, 255]); |
| 536 |
| 537 debug("test that NONE draws nothing"); |
| 538 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); |
| 539 ext.drawBuffersWEBGL(nones); |
| 540 gl.useProgram(redProgram); |
| 541 wtu.clearAndDrawUnitQuad(gl); |
| 542 |
| 543 checkAttachmentsForColor(attachments, [0, 255, 0, 255]); |
| 544 |
| 545 debug("test that gl_FragColor broadcasts"); |
| 546 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); |
| 547 ext.drawBuffersWEBGL(bufs); |
| 548 gl.useProgram(redProgram); |
| 549 wtu.drawUnitQuad(gl); |
| 550 |
| 551 checkAttachmentsForColor(attachments, [255, 0, 0, 255]); |
| 552 |
| 553 if (maxUsable > 1) { |
| 554 var bufs1 = makeColorAttachmentArray(maxUsable); |
| 555 var bufs2 = makeColorAttachmentArray(maxUsable); |
| 556 for (var ii = 0; ii < maxUsable; ++ii) { |
| 557 if (ii < half) { |
| 558 bufs1[ii] = gl.NONE; |
| 559 } else { |
| 560 bufs2[ii] = gl.NONE; |
| 561 } |
| 562 } |
| 563 |
| 564 debug("test setting first half to NONE and clearing"); |
| 565 |
| 566 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); |
| 567 ext.drawBuffersWEBGL(bufs1); |
| 568 gl.clearColor(0, 1, 0, 1); |
| 569 gl.clear(gl.COLOR_BUFFER_BIT); |
| 570 |
| 571 checkAttachmentsForColorFn(attachments, function(attachment, index) { |
| 572 return index < half ? [255, 0, 0, 255] : [0, 255, 0, 255]; |
| 573 }); |
| 574 |
| 575 debug("test setting first half to NONE and drawing"); |
| 576 |
| 577 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); |
| 578 gl.useProgram(drawProgram); |
| 579 wtu.drawUnitQuad(gl); |
| 580 |
| 581 checkAttachmentsForColorFn(attachments, function(attachment, index) { |
| 582 return index < half ? [255, 0, 0, 255] : attachment.color; |
| 583 }); |
| 584 |
| 585 debug("test setting second half to NONE and clearing"); |
| 586 |
| 587 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); |
| 588 ext.drawBuffersWEBGL(bufs); |
| 589 gl.clearColor(1, 0, 0, 1); |
| 590 gl.clear(gl.COLOR_BUFFER_BIT); |
| 591 ext.drawBuffersWEBGL(bufs2); |
| 592 gl.clearColor(0, 0, 1, 1); |
| 593 gl.clear(gl.COLOR_BUFFER_BIT); |
| 594 checkAttachmentsForColorFn(attachments, function(attachment, index) { |
| 595 return index < half ? [0, 0, 255, 255] : [255, 0, 0, 255]; |
| 596 }); |
| 597 |
| 598 debug("test setting second half to NONE and drawing"); |
| 599 |
| 600 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); |
| 601 gl.useProgram(drawProgram); |
| 602 wtu.drawUnitQuad(gl); |
| 603 |
| 604 checkAttachmentsForColorFn(attachments, function(attachment, index) { |
| 605 return index < half ? attachment.color : [255, 0, 0, 255]; |
| 606 }); |
| 607 |
| 608 gl.bindFramebuffer(gl.FRAMEBUFFER, halfFB1); |
| 609 ext.drawBuffersWEBGL(bufs); |
| 610 drawAndCheckAttachments( |
| 611 halfFB1, "framebuffer that only has first half of attachments", |
| 612 function(attachment, index) { |
| 613 return index < half; |
| 614 }); |
| 615 |
| 616 gl.bindFramebuffer(gl.FRAMEBUFFER, halfFB2); |
| 617 ext.drawBuffersWEBGL(bufs); |
| 618 drawAndCheckAttachments( |
| 619 halfFB2, "framebuffer that only has second half of attachments", |
| 620 function(attachment, index) { |
| 621 return index >= half; |
| 622 }); |
| 623 |
| 624 if (maxUsable > 2) { |
| 625 gl.bindFramebuffer(gl.FRAMEBUFFER, endsFB); |
| 626 ext.drawBuffersWEBGL(bufs); |
| 627 drawAndCheckAttachments( |
| 628 endsFB, "framebuffer that only has first and last attachments", |
| 629 function(attachment, index) { |
| 630 return index == 0 || index == (maxUsable - 1); |
| 631 }); |
| 632 |
| 633 gl.bindFramebuffer(gl.FRAMEBUFFER, middleFB); |
| 634 ext.drawBuffersWEBGL(bufs); |
| 635 drawAndCheckAttachments( |
| 636 middleFB, |
| 637 "framebuffer that has all but the first and last attachments", |
| 638 function(attachment, index) { |
| 639 return index != 0 && index != (maxUsable - 1); |
| 640 }); |
| 641 } |
| 642 } |
| 643 |
| 644 debug("test switching between fbos keeps drawbuffer state"); |
| 645 gl.bindFramebuffer(gl.FRAMEBUFFER, fb2); |
| 646 ext.drawBuffersWEBGL(nones); |
| 647 |
| 648 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); |
| 649 ext.drawBuffersWEBGL(bufs); |
| 650 gl.clearColor(1, 0, 0, 1); |
| 651 gl.clear(gl.COLOR_BUFFER_BIT); |
| 652 checkAttachmentsForColor(attachments, [255, 0, 0, 255]); |
| 653 |
| 654 gl.bindFramebuffer(gl.FRAMEBUFFER, fb2); |
| 655 gl.useProgram(drawProgram); |
| 656 wtu.drawUnitQuad(gl); |
| 657 checkAttachmentsForColor(attachments, [255, 0, 0, 255]); |
| 658 |
| 659 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); |
| 660 gl.useProgram(drawProgram); |
| 661 wtu.drawUnitQuad(gl); |
| 662 checkAttachmentsForColor(attachments); |
| 663 |
| 664 debug("test queries"); |
| 665 debug("check framebuffer with all attachments on"); |
| 666 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); |
| 667 for (var ii = 0; ii < maxUsable; ++ii) { |
| 668 shouldBe("gl.getParameter(ext.DRAW_BUFFER0_WEBGL + " + ii + ")", "gl.COLOR_A
TTACHMENT0 + " + ii); |
| 669 } |
| 670 |
| 671 debug("check framebuffer with all attachments off"); |
| 672 gl.bindFramebuffer(gl.FRAMEBUFFER, fb2); |
| 673 for (var ii = 0; ii < maxUsable; ++ii) { |
| 674 shouldBe("gl.getParameter(ext.DRAW_BUFFER0_WEBGL + " + ii + ")", "gl.NONE"); |
| 675 } |
| 676 |
| 677 debug("test attachment size mis-match"); |
| 678 gl.bindTexture(gl.TEXTURE_2D, attachments[0].texture); |
| 679 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width * 2, height, 0, gl.RGBA, gl.UNS
IGNED_BYTE, null); |
| 680 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); |
| 681 shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMP
LETE"); |
| 682 gl.bindFramebuffer(gl.FRAMEBUFFER, fb2); |
| 683 shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMP
LETE"); |
| 684 |
| 685 gl.deleteFramebuffer(fb); |
| 686 gl.deleteFramebuffer(fb2); |
| 687 gl.deleteFramebuffer(halfFB1); |
| 688 gl.deleteFramebuffer(halfFB2); |
| 689 attachments.forEach(function(attachment) { |
| 690 gl.deleteTexture(attachment.texture); |
| 691 }); |
| 692 gl.deleteProgram(checkProgram); |
| 693 gl.deleteProgram(redProgram); |
| 694 gl.deleteProgram(drawProgram); |
| 695 } |
| 696 |
| 697 debug(""); |
| 698 var successfullyParsed = true; |
| 699 </script> |
| 700 <script src="../../resources/js-test-post.js"></script> |
| 701 |
| 702 </body> |
| 703 </html> |
OLD | NEW |