Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / webgl / src / sdk / tests / conformance2 / core / draw-buffers.html
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 Draw Buffers Conformance Tests</title>
33 <link rel="stylesheet" href="../../resources/js-test-style.css"/>
34 <script src="../../resources/js-test-pre.js"></script>
35 <script src="../../conformance/resources/webgl-test-utils.js"></script>
36 </head>
37 <body>
38 <div id="description"></div>
39 <canvas id="canvas" width="64" height="64"> </canvas>
40 <div id="console"></div>
41 <script id="vshader" type="x-shader/x-vertex">
42 attribute vec4 a_position;
43 void main() {
44     gl_Position = a_position;
45 }
46 </script>
47 <script id="fshader" type="x-shader/x-fragment">
48 #version 300 es
49 precision mediump float;
50 uniform vec4 u_colors[$(numDrawingBuffers)];
51 void main() {
52     for (int i = 0; i < $(numDrawingBuffers); ++i) {
53         gl_FragData[i] = u_colors[i];
54     }
55 }
56 </script>
57 <script id="fshaderRed" type="x-shader/x-fragment">
58 precision mediump float;
59 void main() {
60     gl_FragColor = vec4(1,0,0,1);
61 }
62 </script>
63 <script id="fshaderBuiltInConstEnabled" type="x-shader/x-fragment">
64 precision mediump float;
65 void main() {
66     gl_FragColor = (gl_MaxDrawBuffers == $(numDrawingBuffers)) ? vec4(0,1,0,1) : vec4(1,0,0,1);
67 }
68 </script>
69 <script>
70 "use strict";
71 description("This test verifies the functionality of Multiple Render Targets.");
72
73 debug("");
74
75 var wtu = WebGLTestUtils;
76 var canvas = document.getElementById("canvas");
77 var output = document.getElementById("console");
78 var gl = wtu.create3DContext(canvas, null, 2);
79
80 if (!gl) {
81   testFailed("WebGL context does not exist");
82 } else {
83   testPassed("WebGL context exists");
84
85   runShadersTest();
86   runAttachmentTest();
87   runDrawTests();
88
89   wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
90 }
91
92 function createDrawBuffersProgram(scriptId, sub) {
93   var fsource = wtu.getScript(scriptId);
94   fsource = wtu.replaceParams(fsource, sub);
95   wtu.addShaderSource(output, "fragment shader", fsource);
96   return wtu.setupProgram(gl, ["vshader", fsource], ["a_position"]);
97 }
98
99 function runShadersTest() {
100   debug("");
101   debug("test shaders");
102
103   var sub = {numDrawingBuffers: gl.getParameter(gl.MAX_DRAW_BUFFERS)};
104   var program = createDrawBuffersProgram("fshaderBuiltInConstEnabled", sub);
105   wtu.setupUnitQuad(gl);
106   wtu.clearAndDrawUnitQuad(gl);
107   wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
108   gl.deleteProgram(program);
109   wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
110 }
111
112 function makeArray(size, value) {
113   var array = []
114   for (var ii = 0; ii < size; ++ii) {
115     array.push(value);
116   }
117   return array;
118 }
119
120 function makeColorAttachmentArray(size) {
121   var array = []
122   for (var ii = 0; ii < size; ++ii) {
123     array.push(gl.COLOR_ATTACHMENT0 + ii);
124   }
125   return array;
126 }
127
128 function runAttachmentTest() {
129   debug("");
130   debug("test attachment enabled");
131
132   var maxDrawingBuffers = gl.getParameter(gl.MAX_DRAW_BUFFERS);
133   var maxColorAttachments = gl.getParameter(gl.MAX_COLOR_ATTACHMENTS);
134
135   var tex = gl.createTexture();
136   var fb = gl.createFramebuffer();
137   gl.bindTexture(gl.TEXTURE_2D, tex);
138   gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
139   gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + maxColorAttachments, gl.TEXTURE_2D, tex, 0);
140   wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "should not be able to attach pass the max attachment point: gl.COLOR_ATTACHMENT0 + " + maxColorAttachments);
141   gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + maxColorAttachments - 1, gl.TEXTURE_2D, tex, 0);
142   wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to attach to the max attachment point: gl.COLOR_ATTACHMENT0 + " + (maxColorAttachments - 1));
143   gl.drawBuffers(makeArray(maxDrawingBuffers, gl.NONE));
144   wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to call drawBuffers with array NONE of size " + maxColorAttachments);
145   var bufs = makeColorAttachmentArray(maxDrawingBuffers);
146   gl.drawBuffers(bufs);
147   wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to call drawBuffers with array attachments of size " + maxColorAttachments);
148   bufs[0] = gl.NONE;
149   gl.drawBuffers(bufs);
150   wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to call drawBuffers with mixed array attachments of size " + maxColorAttachments);
151   if (maxDrawingBuffers > 1) {
152     bufs[0] = gl.COLOR_ATTACHMENT1;
153     bufs[1] = gl.COLOR_ATTACHMENT0;
154     gl.drawBuffers(bufs);
155     glErrorShouldBe(gl, gl.INVALID_OPERATION, "should not be able to call drawBuffers with out of order attachments of size " + maxColorAttachments);
156     var bufs = makeColorAttachmentArray(Math.floor(maxDrawingBuffers / 2));
157     glErrorShouldBe(gl, gl.NO_ERROR, "should not be able to call drawBuffers with short array of attachments of size " + maxColorAttachments);
158   }
159
160   gl.deleteFramebuffer(fb);
161   gl.deleteTexture(tex);
162   wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
163 }
164
165 function makeColorByIndex(index) {
166   var low = (index - 1) % 15 + 1;
167   var high = (index - 1) / 15;
168
169   var zeroOrOne = function(v) {
170     return v ? 1 : 0;
171   };
172
173   var oneOrTwo = function(v) {
174     return v ? 2 : 1;
175   }
176
177   var makeComponent = function(b0, b1, b2) {
178     return Math.floor(255 * zeroOrOne(b0) / oneOrTwo(b1) / oneOrTwo(b2));
179   };
180   return [
181     makeComponent(low & (1 << 0), high & (1 << 0), high & (1 << 4)),
182     makeComponent(low & (1 << 1), high & (1 << 1), high & (1 << 5)),
183     makeComponent(low & (1 << 2), high & (1 << 2), high & (1 << 6)),
184     makeComponent(low & (1 << 3), high & (1 << 3), high & (1 << 7)),
185   ];
186 }
187
188 function runDrawTests() {
189   debug("");
190   debug("--------- draw tests -----------");
191   var fb = gl.createFramebuffer();
192   var fb2 = gl.createFramebuffer();
193   var halfFB1 = gl.createFramebuffer();
194   var halfFB2 = gl.createFramebuffer();
195   var endsFB = gl.createFramebuffer();
196   var middleFB = gl.createFramebuffer();
197
198   var maxDrawingBuffers = gl.getParameter(gl.MAX_DRAW_BUFFERS);
199   var maxColorAttachments = gl.getParameter(gl.MAX_COLOR_ATTACHMENTS);
200   var maxUniformVectors = gl.getParameter(gl.MAX_FRAGMENT_UNIFORM_VECTORS);
201   var maxUsable = Math.min(maxDrawingBuffers, maxColorAttachments, maxUniformVectors);
202   var half = Math.floor(maxUsable / 2);
203   var bufs = makeColorAttachmentArray(maxUsable);
204   var nones = makeArray(maxUsable, gl.NONE);
205
206   [fb, fb2, halfFB1, halfFB2, endsFB, middleFB].forEach(function(fbo) {
207     gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
208     gl.drawBuffers(bufs);
209   });
210
211   var checkProgram = wtu.setupTexturedQuad(gl);
212   var redProgram = wtu.setupProgram(gl, ["vshader", "fshaderRed"], ["a_position"]);
213   var drawProgram = createDrawBuffersProgram("fshader", {numDrawingBuffers: maxDrawingBuffers});
214   var width = 64;
215   var height = 64;
216   var attachments = [];
217   // Makes 6 framebuffers.
218   // fb and fb2 have all the attachments.
219   // halfFB1 has the first half of the attachments
220   // halfFB2 has the second half of the attachments
221   // endsFB has the first and last attachments
222   // middleFB has all but the first and last attachments
223   for (var ii = 0; ii < maxUsable; ++ii) {
224     var tex = gl.createTexture();
225     gl.bindTexture(gl.TEXTURE_2D, tex);
226     gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
227     gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
228     gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
229     gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
230     gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
231     gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
232     gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ii, gl.TEXTURE_2D, tex, 0);
233     gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
234     gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ii, gl.TEXTURE_2D, tex, 0);
235     gl.bindFramebuffer(gl.FRAMEBUFFER, ii < half ? halfFB1 : halfFB2);
236     gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ii, gl.TEXTURE_2D, tex, 0);
237     gl.bindFramebuffer(gl.FRAMEBUFFER, (ii == 0 || ii == (maxUsable - 1)) ? endsFB : middleFB);
238     gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ii, gl.TEXTURE_2D, tex, 0);
239     var location = gl.getUniformLocation(drawProgram, "u_colors[" + ii + "]");
240     var color = makeColorByIndex(ii + 1);
241     var floatColor = [color[0] / 255, color[1] / 255, color[2] / 255, color[3] / 255];
242     gl.uniform4fv(location, floatColor);
243     attachments.push({
244       texture: tex,
245       location: location,
246       color: color
247     });
248   }
249   gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
250   shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
251   gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
252   shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
253
254   var checkAttachmentsForColorFn = function(attachments, colorFn) {
255     gl.bindFramebuffer(gl.FRAMEBUFFER, null);
256     gl.useProgram(checkProgram);
257     attachments.forEach(function(attachment, index) {
258       gl.bindTexture(gl.TEXTURE_2D, attachment.texture);
259       wtu.clearAndDrawUnitQuad(gl);
260       var expectedColor = colorFn(attachment, index);
261       var tolerance = 0;
262       expectedColor.forEach(function(v) {
263         if (v != 0 && v != 255) {
264           tolerance = 8;
265         }
266       });
267       wtu.checkCanvas(gl, expectedColor, "attachment " + index + " should be " + expectedColor.toString(), tolerance);
268     });
269     debug("");
270   };
271
272   var checkAttachmentsForColor = function(attachments, color) {
273     checkAttachmentsForColorFn(attachments, function(attachment, index) {
274       return color || attachment.color;
275     });
276   };
277
278   var drawAndCheckAttachments = function(testFB, msg, testFn) {
279     debug("test clearing " + msg);
280
281     gl.bindFramebuffer(gl.FRAMEBUFFER, testFB);
282
283     attachments.forEach(function(attachment, index) {
284       debug("attachment: " + index + " = " + wtu.glEnumToString(gl, gl.getParameter(gl.DRAW_BUFFER0 + index)) +
285             ", " + wtu.glEnumToString(gl, gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + index, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)));
286     });
287
288     if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
289       debug("framebuffer not complete");
290       debug("");
291       return;
292     }
293
294     // Clear all the attachments
295     gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
296     gl.clearColor(0, 0, 0, 0);
297     gl.clear(gl.COLOR_BUFFER_BIT);
298     //checkAttachmentsForColorFn(attachments, function(attachment, index) {
299     //  return [0, 0, 0, 0];
300     //});
301     //debug("--");
302
303     // Clear some attachments using testFB
304     gl.bindFramebuffer(gl.FRAMEBUFFER, testFB);
305
306     gl.clearColor(0, 1, 0, 1);
307     gl.clear(gl.COLOR_BUFFER_BIT);
308     checkAttachmentsForColorFn(attachments, function(attachment, index) {
309       return testFn(attachment, index) ? [0, 255, 0, 255] : [0, 0, 0, 0];
310     });
311
312     debug("test drawing to " + msg);
313
314     // Draw to some attachments using testFB
315     gl.useProgram(drawProgram);
316     gl.bindFramebuffer(gl.FRAMEBUFFER, testFB);
317     wtu.drawUnitQuad(gl);
318
319     checkAttachmentsForColorFn(attachments, function(attachment, index) {
320       return testFn(attachment, index) ? attachment.color : [0, 0, 0, 0];
321     });
322   };
323
324   gl.useProgram(drawProgram);
325   gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
326   gl.drawBuffers(bufs);
327   gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
328   gl.drawBuffers(bufs);
329
330   wtu.drawUnitQuad(gl);
331
332   debug("test that each texture got the correct color.");
333
334   checkAttachmentsForColor(attachments);
335
336   debug("test clearing clears all the textures");
337   gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
338   gl.clearColor(0, 1, 0, 1);
339   gl.clear(gl.COLOR_BUFFER_BIT);
340
341   checkAttachmentsForColor(attachments, [0, 255, 0, 255]);
342
343   debug("test that NONE draws nothing");
344   gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
345   gl.drawBuffers(nones);
346   gl.useProgram(redProgram);
347   wtu.clearAndDrawUnitQuad(gl);
348
349   checkAttachmentsForColor(attachments, [0, 255, 0, 255]);
350
351   debug("test that gl_FragColor broadcasts");
352   gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
353   gl.drawBuffers(bufs);
354   gl.useProgram(redProgram);
355   wtu.drawUnitQuad(gl);
356
357   checkAttachmentsForColor(attachments, [255, 0, 0, 255]);
358
359   if (maxUsable > 1) {
360     var bufs1 = makeColorAttachmentArray(maxUsable);
361     var bufs2 = makeColorAttachmentArray(maxUsable);
362     for (var ii = 0; ii < maxUsable; ++ii) {
363       if (ii < half) {
364         bufs1[ii] = gl.NONE;
365       } else {
366         bufs2[ii] = gl.NONE;
367       }
368     }
369
370     debug("test setting first half to NONE and clearing");
371
372     gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
373     gl.drawBuffers(bufs1);
374     gl.clearColor(0, 1, 0, 1);
375     gl.clear(gl.COLOR_BUFFER_BIT);
376
377     checkAttachmentsForColorFn(attachments, function(attachment, index) {
378       return index < half ? [255, 0, 0, 255] : [0, 255, 0, 255];
379     });
380
381     debug("test setting first half to NONE and drawing");
382
383     gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
384     gl.useProgram(drawProgram);
385     wtu.drawUnitQuad(gl);
386
387     checkAttachmentsForColorFn(attachments, function(attachment, index) {
388       return index < half ? [255, 0, 0, 255] : attachment.color;
389     });
390
391     debug("test setting second half to NONE and clearing");
392
393     gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
394     gl.drawBuffers(bufs);
395     gl.clearColor(1, 0, 0, 1);
396     gl.clear(gl.COLOR_BUFFER_BIT);
397     gl.drawBuffers(bufs2);
398     gl.clearColor(0, 0, 1, 1);
399     gl.clear(gl.COLOR_BUFFER_BIT);
400     checkAttachmentsForColorFn(attachments, function(attachment, index) {
401       return index < half ? [0, 0, 255, 255] : [255, 0, 0, 255];
402     });
403
404     debug("test setting second half to NONE and drawing");
405
406     gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
407     gl.useProgram(drawProgram);
408     wtu.drawUnitQuad(gl);
409
410     checkAttachmentsForColorFn(attachments, function(attachment, index) {
411       return index < half ? attachment.color : [255, 0, 0, 255];
412     });
413
414     gl.bindFramebuffer(gl.FRAMEBUFFER, halfFB1);
415     gl.drawBuffers(bufs);
416     drawAndCheckAttachments(
417       halfFB1, "framebuffer that only has first half of attachments",
418       function(attachment, index) {
419         return index < half;
420       });
421
422     gl.bindFramebuffer(gl.FRAMEBUFFER, halfFB2);
423     gl.drawBuffers(bufs);
424     drawAndCheckAttachments(
425       halfFB2, "framebuffer that only has second half of attachments",
426       function(attachment, index) {
427         return index >= half;
428       });
429
430     if (maxUsable > 2) {
431       gl.bindFramebuffer(gl.FRAMEBUFFER, endsFB);
432       gl.drawBuffers(bufs);
433       drawAndCheckAttachments(
434         endsFB, "framebuffer that only has first and last attachments",
435         function(attachment, index) {
436           return index == 0 || index == (maxUsable - 1);
437         });
438
439       gl.bindFramebuffer(gl.FRAMEBUFFER, middleFB);
440       gl.drawBuffers(bufs);
441       drawAndCheckAttachments(
442         middleFB,
443         "framebuffer that has all but the first and last attachments",
444         function(attachment, index) {
445           return index != 0 && index != (maxUsable - 1);
446         });
447     }
448   }
449
450   debug("test switching between fbos keeps drawbuffer state");
451   gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
452   gl.drawBuffers(nones);
453
454   gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
455   gl.drawBuffers(bufs);
456   gl.clearColor(1, 0, 0, 1);
457   gl.clear(gl.COLOR_BUFFER_BIT);
458   checkAttachmentsForColor(attachments, [255, 0, 0, 255]);
459
460   gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
461   gl.useProgram(drawProgram);
462   wtu.drawUnitQuad(gl);
463   checkAttachmentsForColor(attachments, [255, 0, 0, 255]);
464
465   gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
466   gl.useProgram(drawProgram);
467   wtu.drawUnitQuad(gl);
468   checkAttachmentsForColor(attachments);
469
470   debug("test queries");
471   debug("check framebuffer with all attachments on");
472   gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
473   for (var ii = 0; ii < maxUsable; ++ii) {
474     shouldBe("gl.getParameter(gl.DRAW_BUFFER0 + " + ii + ")", "gl.COLOR_ATTACHMENT0 + " + ii);
475   }
476
477   debug("check framebuffer with all attachments off");
478   gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
479   for (var ii = 0; ii < maxUsable; ++ii) {
480     shouldBe("gl.getParameter(gl.DRAW_BUFFER0 + " + ii + ")", "gl.NONE");
481   }
482
483   debug("test attachment size mis-match");
484   gl.bindTexture(gl.TEXTURE_2D, attachments[0].texture);
485   gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width * 2, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
486   gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
487   shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE");
488   gl.bindFramebuffer(gl.FRAMEBUFFER, fb2);
489   shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE");
490
491   gl.deleteFramebuffer(fb);
492   gl.deleteFramebuffer(fb2);
493   gl.deleteFramebuffer(halfFB1);
494   gl.deleteFramebuffer(halfFB2);
495   attachments.forEach(function(attachment) {
496     gl.deleteTexture(attachment.texture);
497   });
498   gl.deleteProgram(checkProgram);
499   gl.deleteProgram(redProgram);
500   gl.deleteProgram(drawProgram);
501 }
502
503 debug("");
504 var successfullyParsed = true;
505 </script>
506 <script src="../../resources/js-test-post.js"></script>
507
508 </body>
509 </html>