texImage2D for a half-float texture only accepts null
[WebKit-https.git] / LayoutTests / fast / canvas / webgl / oes-texture-half-float.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 OES_texture_half_float Conformance Tests</title>
33 <script src="resources/desktop-gl-constants.js" type="text/javascript"></script>
34 <script src="../../../resources/js-test.js"></script>
35 <script src="resources/webgl-test.js"></script>
36 <script src="resources/webgl-test-utils.js"></script></head>
37 <body>
38 <div id="description"></div>
39 <canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
40 <canvas id="canvas2d" style="width: 50px; height: 50px;"> </canvas>
41 <div id="console"></div>
42 <script id="testFragmentShader" type="x-shader/x-fragment">
43 precision mediump float;
44 uniform sampler2D tex;
45 uniform vec4 subtractor;
46 varying vec2 texCoord;
47 void main()
48 {
49     vec4 color = texture2D(tex, texCoord);
50     if (abs(color.r - subtractor.r) +
51         abs(color.g - subtractor.g) +
52         abs(color.b - subtractor.b) +
53         abs(color.a - subtractor.a) < 8.0) {
54         gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
55     } else {
56         gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
57     }
58 }
59 </script>
60 <!-- Shaders for testing half-floating-point render targets -->
61 <script id="positionVertexShader" type="x-shader/x-vertex">
62 attribute vec4 vPosition;
63 void main()
64 {
65     gl_Position = vPosition;
66 }
67 </script>
68 <script id="floatingPointFragmentShader" type="x-shader/x-fragment">
69 void main()
70 {
71     gl_FragColor = vec4(10000.0, 10000.0, 10000.0, 10000.0);
72 }
73 </script>
74 <script>
75 if (window.testRunner)
76     window.testRunner.dumpAsText();
77
78 "use strict"
79 description("This test verifies the functionality of OES_texture_half_float with null/non-null ArrayBufferView");
80
81 debug("");
82 var wtu = WebGLTestUtils;
83 var canvas = document.getElementById("canvas");
84 var colorCanvas = document.getElementById("canvas2d");
85 colorCanvas.width = 2;
86 colorCanvas.height = 2;
87 var ctx = colorCanvas.getContext("2d");
88 ctx.fillStyle = "rgb(255,0,0)";
89 ctx.fillRect(0, 0, 2, 2);
90 var gl = wtu.create3DContext(canvas);
91 // This constant must be defined in order to run the texture creation test without the extension enabled.
92 var halfFloatOESEnum = 0x8D61;
93 var ext = null;
94
95 if (!gl) {
96     testFailed("WebGL context does not exists");
97 } else {
98     testPassed("WebGL context exists");
99
100     // Verify that allocation of texture fails if extension is not enabled
101     runTextureCreationTest(false);
102     ext = gl.getExtension("OES_texture_half_float")
103     if (!ext) {
104         testPassed("No OES_texture_half_float support. This is legal");
105     } else {
106         testPassed("Successfully enabled OES_texture_half_float extension");
107
108         var program = wtu.setupTexturedQuad(gl);
109
110         // Check if creation of texture succeed's with various formats and null ArrayBufferView
111         var formats = [
112           { format: gl.RGBA,            expected: [255,   0,   0, 255], },
113           { format: gl.RGB,             expected: [255,   0,   0, 255], },
114           { format: gl.LUMINANCE,       expected: [255, 255, 255, 255], },
115           { format: gl.ALPHA,           expected: [  0,   0,   0, 255], },
116           { format: gl.LUMINANCE_ALPHA, expected: [255, 255, 255, 255], },
117         ];
118         formats.forEach(function(f) {
119             runTextureCreationTest(true, f.format, null, f.expected);
120         });
121         
122         // Texture creation should fail when passed with non-null, non-Uint16 ArrayBufferView
123         formats.forEach(function(f) {
124             var width = 2;
125             var height = 2;
126             var format = f.format;
127             
128             // Float32Array
129             var float32Data = new Float32Array(width * height * getNumberOfChannels(format));
130             for (var ii = 0; ii < float32Data.length; ii++) {
131                 float32Data[ii] = 1000;
132             }
133             runTextureCreationTest(true, format, float32Data, null);
134
135             // Int16Array
136             var int16Data = new Int16Array(width * height * getNumberOfChannels(format));
137             for (var ii = 0; ii <  int16Data.length; ii++) {
138                 int16Data[ii] = 1000;
139             }
140             runTextureCreationTest(true, format, int16Data, null);
141         });
142
143         // Test that Uint16 encoded half float values can be used as texture data.
144         
145         // First test that values in the 0-1 range can be written and read.
146         var halfFloatOneThird = 0x3555; // Half float 1/3
147         var uint16Formats = [
148           { format: gl.RGBA,            expected: [85, 85, 85,  85], },
149           { format: gl.RGB,             expected: [85, 85, 85, 255], },
150           { format: gl.LUMINANCE,       expected: [85, 85, 85, 255], },
151           { format: gl.ALPHA,           expected: [ 0,  0,  0,  85], },
152           { format: gl.LUMINANCE_ALPHA, expected: [85, 85, 85,  85], },
153         ];
154
155         uint16Formats.forEach(function(f) {
156             var width = 2;
157             var height = 2;
158             var format = f.format;
159
160             var uint16Data = new Uint16Array(width * height * getNumberOfChannels(format));
161             for (var ii = 0; ii <  uint16Data.length; ii++) {
162                 uint16Data[ii] = halfFloatOneThird;
163             }
164             runTextureCreationTest(true, format, uint16Data, f.expected);
165         });
166
167         // Next check that values outside the 0-1 range can be written.
168         var halfFloatTenK = 0x70E2; // Half float 10000
169         var uint16Formats2 = [
170           { format: gl.RGBA, subtractor: [10000, 10000, 10000, 10000], },
171           { format: gl.RGB,  subtractor: [10000, 10000, 10000, 1], },
172         ];
173
174         uint16Formats2.forEach(function(f) {
175             var width = 2;
176             var height = 2;
177             var format = f.format;
178
179             var uint16Data = new Uint16Array(width * height * getNumberOfChannels(format));
180             for (var ii = 0; ii <  uint16Data.length; ii++) {
181                 uint16Data[ii] = halfFloatTenK;
182             }
183             runRenderTest(format, f.subtractor, uint16Data);
184         });
185
186         // Check if attaching texture as FBO target succeeds (Not mandatory)
187         runRenderTest(gl.RGBA, [10000, 10000, 10000, 10000], null);
188         runRenderTest(gl.RGB, [10000, 10000, 10000, 1], null);
189
190         // Check of getExtension() returns same object
191         runUniqueObjectTest();
192     }
193 }
194
195 function getNumberOfChannels(format)
196 {
197     if (format == gl.RGBA)
198         return 4;
199     else if (format == gl.RGB)
200         return 3;
201     else if (format == gl.LUMINANCE || format == gl.ALPHA)
202         return 1;
203     else if (format == gl.LUMINANCE_ALPHA)
204         return 2;
205 }
206
207 function getFormatName(format)
208 {
209     if (format == gl.RGBA)
210         return "RGBA";
211     else if (format == gl.RGB)
212         return "RGB";
213     else if (format == gl.LUMINANCE)
214         return "LUMINANCE";
215     else if (format == gl.ALPHA)
216         return "ALPHA";
217     else if (format == gl.LUMINANCE_ALPHA)
218         return "LUMINANCE_ALPHA";
219 }
220
221 function allocateTexture()
222 {
223     var texture = gl.createTexture();
224     gl.bindTexture(gl.TEXTURE_2D, texture);
225     gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
226     gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
227     gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
228     gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
229     wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texture parameter setup should succeed");
230     return texture;
231 }
232
233 function runTextureCreationTest(extensionEnabled, opt_format, opt_data, opt_expected)
234 {
235     var format = opt_format || gl.RGBA;
236     var data = opt_data || null;
237     var expectSuccess = true;
238     
239     if (!extensionEnabled || !opt_expected)
240         expectSuccess = false;
241     debug("Testing texture creation with extension " + (extensionEnabled ? "enabled" : "disabled") +
242           ", format " + getFormatName(format) + ", and data " + (data ? "non-null" : "null") +
243           ". Expect " + (expectSuccess ? "Success" : "Failure"));   
244
245     var texture = allocateTexture();
246     var width = 2;
247     var height = 2;
248     gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, format, halfFloatOESEnum, data);
249     if(!extensionEnabled) {
250         wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Half floating point texture must be disallowed if OES_texture_half_float isn't enabled");
251         return;
252     } else if (!opt_expected) {
253         wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Half floating point texture allocation must be disallowed when ArrayBufferView is not-null and not-Uint16");
254         return;
255     } else {
256         wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Half floating point texture allocation should succeed if OES_texture_half_float is enabled");
257
258         if (!data) {
259             gl.texImage2D(gl.TEXTURE_2D, 0, format, format, halfFloatOESEnum, colorCanvas);
260         }
261         wtu.clearAndDrawUnitQuad(gl);
262         wtu.checkCanvas(gl, opt_expected);
263         // Check that linear fails.
264         gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
265         wtu.clearAndDrawUnitQuad(gl);
266         wtu.checkCanvas(gl, [0, 0, 0, 255], "should be black");
267     }
268
269 }
270
271 function checkRenderingResults()
272 {
273     wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
274 }
275
276 function runRenderTest(format, subtractor, data)
277 {
278     var formatString = wtu.glEnumToString(gl, format);
279
280     debug("");
281
282     if (!data) {
283         debug("Testing half floating point " + formatString + " render target");
284     } else {
285         debug("Testing half floating point " + formatString + " from a Uint16Array");
286     }
287
288     var texture = allocateTexture();
289     var width = 2;
290     var height = 2;
291
292     gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, format, ext.HALF_FLOAT_OES, data);
293     wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Half floating point texture allocation should succeed if OES_texture_half_float is enabled");
294
295     if (!data) {
296         // Try to use this texture as render target
297         var fbo = gl.createFramebuffer();
298         gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
299         gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
300         gl.bindTexture(gl.TEXTURE_2D, null);
301
302         // It is legal for a WebGL implementation exposing the OES_texture_half_float extension to
303         // support half floating point textures but not as attachments to framebuffer objects.
304         if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) {
305             debug("Half floating point render targets not supported -- this is legal");
306             return;
307         }
308
309         var renderProgram =
310             wtu.setupProgram(gl,
311                              ["positionVertexShader", "floatingPointFragmentShader"],
312                              ['vPosition'],
313                              [0]);
314         wtu.drawUnitQuad(gl);
315         wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Rendering to half floating point texture should succeed");
316     }
317
318     // Now sample from the half floating-point texture and verify we got the correct values.
319     var texturedShaders = [
320       wtu.setupSimpleTextureVertexShader(gl),
321           "testFragmentShader"
322       ];
323     var testProgram =
324         wtu.setupProgram(gl,
325                         [wtu.setupSimpleTextureVertexShader(gl), "testFragmentShader"],
326                         ['vPosition', 'texCoord0'],
327                         [0, 1]);
328     var quadParameters = wtu.setupUnitQuad(gl, 0, 1);
329     gl.bindFramebuffer(gl.FRAMEBUFFER, null);
330     gl.bindTexture(gl.TEXTURE_2D, texture);
331     gl.useProgram(testProgram);
332     gl.uniform4fv(gl.getUniformLocation(testProgram, "subtractor"), subtractor);
333     wtu.drawUnitQuad(gl);
334     wtu.glErrorShouldBe(gl, gl.NO_ERROR, "rendering from half floating point texture should succeed");
335     checkRenderingResults();
336 }
337
338 function runUniqueObjectTest()
339 {
340     debug("");
341     debug("Testing that getExtension() returns the same object each time");
342     gl.getExtension("OES_texture_half_float").myProperty = 2;
343     gc();
344     shouldBe('gl.getExtension("OES_texture_half_float").myProperty', '2');
345 }
346
347 debug("");
348 var successfullyParsed = true;
349 </script>
350 <script src="../../resources/js-test-post.js"></script>
351
352 </body>
353 </html>