OLD | NEW |
| (Empty) |
1 <!-- | |
2 Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
3 Use of this source code is governed by a BSD-style license that can be | |
4 found in the LICENSE file. | |
5 --> | |
6 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" | |
7 "http://www.w3.org/TR/html4/loose.dtd"> | |
8 <html> | |
9 <head> | |
10 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> | |
11 <title>WebGL OES_standard_derivatives Conformance Tests</title> | |
12 <link rel="stylesheet" href="../resources/js-test-style.css"/> | |
13 <script src="../resources/desktop-gl-constants.js" type="text/javascript"></scri
pt> | |
14 <script src="../resources/js-test-pre.js"></script> | |
15 <script src="resources/webgl-test.js"></script> | |
16 <script src="resources/webgl-test-utils.js"></script> | |
17 </head> | |
18 <body> | |
19 <div id="description"></div> | |
20 <canvas id="canvas" style="width: 50px; height: 50px;"> </canvas> | |
21 <div id="console"></div> | |
22 <!-- Shaders for testing standard derivatives --> | |
23 | |
24 <!-- Shader omitting the required #extension pragma --> | |
25 <script id="missingPragmaFragmentShader" type="x-shader/x-fragment"> | |
26 precision mediump float; | |
27 varying vec2 texCoord; | |
28 void main() { | |
29 float dx = dFdx(texCoord.x); | |
30 float dy = dFdy(texCoord.y); | |
31 float w = fwidth(texCoord.x); | |
32 gl_FragColor = vec4(dx, dy, w, 1.0); | |
33 } | |
34 </script> | |
35 | |
36 <!-- Shader to test macro definition --> | |
37 <script id="macroFragmentShader" type="x-shader/x-fragment"> | |
38 precision mediump float; | |
39 void main() { | |
40 #ifdef GL_OES_standard_derivatives | |
41 gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0); | |
42 #else | |
43 // Error expected | |
44 #error no GL_OES_standard_derivatives; | |
45 #endif | |
46 } | |
47 </script> | |
48 | |
49 <!-- Shader with required #extension pragma --> | |
50 <script id="testFragmentShader" type="x-shader/x-fragment"> | |
51 #extension GL_OES_standard_derivatives : enable | |
52 precision mediump float; | |
53 varying vec2 texCoord; | |
54 void main() { | |
55 float dx = dFdx(texCoord.x); | |
56 float dy = dFdy(texCoord.y); | |
57 float w = fwidth(texCoord.x); | |
58 gl_FragColor = vec4(dx, dy, w, 1.0); | |
59 } | |
60 </script> | |
61 | |
62 <!-- Shaders to test output --> | |
63 <script id="outputVertexShader" type="x-shader/x-vertex"> | |
64 attribute vec4 vPosition; | |
65 varying vec4 position; | |
66 void main() { | |
67 position = vPosition; | |
68 gl_Position = vPosition; | |
69 } | |
70 </script> | |
71 <script id="outputFragmentShader" type="x-shader/x-fragment"> | |
72 #extension GL_OES_standard_derivatives : enable | |
73 precision highp float; | |
74 varying vec4 position; | |
75 void main() { | |
76 float dzdx = dFdx(position.z); | |
77 float dzdy = dFdy(position.z); | |
78 float fw = fwidth(position.z); | |
79 gl_FragColor = vec4(abs(dzdx), abs(dzdy), fw, 1.0); | |
80 } | |
81 </script> | |
82 | |
83 <script> | |
84 description("This test verifies the functionality of the OES_standard_derivative
s extension, if it is available."); | |
85 | |
86 debug(""); | |
87 | |
88 var wtu = WebGLTestUtils; | |
89 var canvas = document.getElementById("canvas"); | |
90 var gl = create3DContext(canvas); | |
91 var ext = null; | |
92 | |
93 if (!gl) { | |
94 testFailed("WebGL context does not exist"); | |
95 } else { | |
96 testPassed("WebGL context exists"); | |
97 | |
98 // Run tests with extension disabled | |
99 runHintTestDisabled(); | |
100 runShaderTests(false); | |
101 | |
102 // Query the extension and store globally so shouldBe can access it | |
103 ext = gl.getExtension("OES_standard_derivatives"); | |
104 if (!ext) { | |
105 testPassed("No OES_standard_derivatives support -- this is legal"); | |
106 | |
107 runSupportedTest(false); | |
108 } else { | |
109 testPassed("Successfully enabled OES_standard_derivatives extension"); | |
110 | |
111 runSupportedTest(true); | |
112 | |
113 runHintTestEnabled(); | |
114 runShaderTests(true); | |
115 runOutputTests(); | |
116 runUniqueObjectTest(); | |
117 } | |
118 } | |
119 | |
120 function runSupportedTest(extensionEnabled) { | |
121 var supported = gl.getSupportedExtensions(); | |
122 if (supported.indexOf("OES_standard_derivatives") >= 0) { | |
123 if (extensionEnabled) { | |
124 testPassed("OES_standard_derivatives listed as supported and getExte
nsion succeeded"); | |
125 } else { | |
126 testFailed("OES_standard_derivatives listed as supported but getExte
nsion failed"); | |
127 } | |
128 } else { | |
129 if (extensionEnabled) { | |
130 testFailed("OES_standard_derivatives not listed as supported but get
Extension succeeded"); | |
131 } else { | |
132 testPassed("OES_standard_derivatives not listed as supported and get
Extension failed -- this is legal"); | |
133 } | |
134 } | |
135 } | |
136 | |
137 function runHintTestDisabled() { | |
138 debug("Testing FRAGMENT_SHADER_DERIVATIVE_HINT_OES with extension disabled")
; | |
139 | |
140 // Use the constant directly as we don't have the extension | |
141 var FRAGMENT_SHADER_DERIVATIVE_HINT_OES = 0x8B8B; | |
142 | |
143 gl.getParameter(FRAGMENT_SHADER_DERIVATIVE_HINT_OES); | |
144 glErrorShouldBe(gl, gl.INVALID_ENUM, "FRAGMENT_SHADER_DERIVATIVE_HINT_OES sh
ould not be queryable if extension is disabled"); | |
145 | |
146 gl.hint(FRAGMENT_SHADER_DERIVATIVE_HINT_OES, gl.DONT_CARE); | |
147 glErrorShouldBe(gl, gl.INVALID_ENUM, "hint should not accept FRAGMENT_SHADER
_DERIVATIVE_HINT_OES if extension is disabled"); | |
148 } | |
149 | |
150 function runHintTestEnabled() { | |
151 debug("Testing FRAGMENT_SHADER_DERIVATIVE_HINT_OES with extension enabled"); | |
152 | |
153 shouldBe("ext.FRAGMENT_SHADER_DERIVATIVE_HINT_OES", "0x8B8B"); | |
154 | |
155 gl.getParameter(ext.FRAGMENT_SHADER_DERIVATIVE_HINT_OES); | |
156 glErrorShouldBe(gl, gl.NO_ERROR, "FRAGMENT_SHADER_DERIVATIVE_HINT_OES query
should succeed if extension is enabled"); | |
157 | |
158 // Default value is DONT_CARE | |
159 if (gl.getParameter(ext.FRAGMENT_SHADER_DERIVATIVE_HINT_OES) == gl.DONT_CARE
) { | |
160 testPassed("Default value of FRAGMENT_SHADER_DERIVATIVE_HINT_OES is DONT
_CARE"); | |
161 } else { | |
162 testFailed("Default value of FRAGMENT_SHADER_DERIVATIVE_HINT_OES is not
DONT_CARE"); | |
163 } | |
164 | |
165 // Ensure that we can set the target | |
166 gl.hint(ext.FRAGMENT_SHADER_DERIVATIVE_HINT_OES, gl.DONT_CARE); | |
167 glErrorShouldBe(gl, gl.NO_ERROR, "hint should accept FRAGMENT_SHADER_DERIVAT
IVE_HINT_OES"); | |
168 | |
169 // Test all the hint modes | |
170 var validModes = ["FASTEST", "NICEST", "DONT_CARE"]; | |
171 var anyFailed = false; | |
172 for (var n = 0; n < validModes.length; n++) { | |
173 var mode = validModes[n]; | |
174 gl.hint(ext.FRAGMENT_SHADER_DERIVATIVE_HINT_OES, gl[mode]); | |
175 if (gl.getParameter(ext.FRAGMENT_SHADER_DERIVATIVE_HINT_OES) != gl[mode]
) { | |
176 testFailed("Round-trip of hint()/getParameter() failed on mode " + m
ode); | |
177 anyFailed = true; | |
178 } | |
179 } | |
180 if (!anyFailed) { | |
181 testPassed("Round-trip of hint()/getParameter() with all supported modes
"); | |
182 } | |
183 } | |
184 | |
185 function runShaderTests(extensionEnabled) { | |
186 debug("Testing various shader compiles with extension " + (extensionEnabled
? "enabled" : "disabled")); | |
187 | |
188 // Expect the macro shader to succeed ONLY if enabled | |
189 var macroFragmentShader = wtu.loadShaderFromScript(gl, "macroFragmentShader"
); | |
190 if (extensionEnabled) { | |
191 if (macroFragmentShader) { | |
192 // Expected result | |
193 testPassed("GL_OES_standard_derivatives defined in shaders when exte
nsion is enabled"); | |
194 } else { | |
195 testFailed("GL_OES_standard_derivatives not defined in shaders when
extension is enabled"); | |
196 } | |
197 } else { | |
198 if (macroFragmentShader) { | |
199 testFailed("GL_OES_standard_derivatives defined in shaders when exte
nsion is disabled"); | |
200 } else { | |
201 testPassed("GL_OES_standard_derivatives not defined in shaders when
extension disabled"); | |
202 } | |
203 } | |
204 | |
205 // Always expect the shader missing the #pragma to fail (whether enabled or
not) | |
206 var missingPragmaFragmentShader = wtu.loadShaderFromScript(gl, "missingPragm
aFragmentShader"); | |
207 if (missingPragmaFragmentShader) { | |
208 testFailed("Shader built-ins allowed without #extension pragma"); | |
209 } else { | |
210 testPassed("Shader built-ins disallowed without #extension pragma"); | |
211 } | |
212 | |
213 // Try to compile a shader using the built-ins that should only succeed if e
nabled | |
214 var testFragmentShader = wtu.loadShaderFromScript(gl, "testFragmentShader"); | |
215 if (extensionEnabled) { | |
216 if (testFragmentShader) { | |
217 testPassed("Shader built-ins compiled successfully when extension en
abled"); | |
218 } else { | |
219 testFailed("Shader built-ins failed to compile when extension enable
d"); | |
220 } | |
221 } else { | |
222 if (testFragmentShader) { | |
223 testFailed("Shader built-ins compiled successfully when extension di
sabled"); | |
224 } else { | |
225 testPassed("Shader built-ins failed to compile when extension disabl
ed"); | |
226 } | |
227 } | |
228 } | |
229 | |
230 function runOutputTests() { | |
231 // This tests does several draws with various values of z. | |
232 // The output of the fragment shader is: | |
233 // [dFdx(z), dFdy(z), fwidth(z), 1.0] | |
234 // The expected math: (note the conversion to uint8) | |
235 // canvas.width = canvas.height = 50 | |
236 // dFdx = totalChange.x / canvas.width = 0.5 / 50.0 = 0.01 | |
237 // dFdy = totalChange.y / canvas.height = 0.5 / 50.0 = 0.01 | |
238 // fw = abs(dFdx + dFdy) = 0.01 + 0.01 = 0.02 | |
239 // r = floor(dFdx * 255) = 3 | |
240 // g = floor(dFdy * 255) = 3 | |
241 // b = floor(fw * 255) = 5 | |
242 | |
243 var e = 2; // Amount of variance to allow in result pixels - may need to be
tweaked higher | |
244 | |
245 debug("Testing various draws for valid built-in function behavior"); | |
246 | |
247 canvas.width = 50; canvas.height = 50; | |
248 gl.viewport(0, 0, canvas.width, canvas.height); | |
249 gl.hint(ext.FRAGMENT_SHADER_DERIVATIVE_HINT_OES, gl.NICEST); | |
250 | |
251 var shaders = [ | |
252 wtu.loadShaderFromScript(gl, "outputVertexShader"), | |
253 wtu.loadShaderFromScript(gl, "outputFragmentShader") | |
254 ]; | |
255 var program = wtu.setupProgram(gl, shaders, ['vPosition', 'texCoord0'], [0,
1]); | |
256 var quadParameters = wtu.setupUnitQuad(gl, 0, 1); | |
257 | |
258 function readLocation(x, y) { | |
259 var pixels = new Uint8Array(1 * 1 * 4); | |
260 var px = Math.floor(x * canvas.width); | |
261 var py = Math.floor(y * canvas.height); | |
262 gl.readPixels(px, py, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels); | |
263 return pixels; | |
264 }; | |
265 function toString(arr) { | |
266 var s = "["; | |
267 for (var n = 0; n < arr.length; n++) { | |
268 s += arr[n]; | |
269 if (n < arr.length - 1) { | |
270 s += ", "; | |
271 } | |
272 } | |
273 return s + "]"; | |
274 }; | |
275 function expectResult(target, successMessage, failureMessage) { | |
276 var locations = [ | |
277 readLocation(0.1, 0.1), | |
278 readLocation(0.9, 0.1), | |
279 readLocation(0.1, 0.9), | |
280 readLocation(0.9, 0.9), | |
281 readLocation(0.5, 0.5) | |
282 ]; | |
283 var anyDiffer = false; | |
284 for (var n = 0; n < locations.length; n++) { | |
285 var source = locations[n]; | |
286 for (var m = 0; m < 4; m++) { | |
287 if (Math.abs(source[m] - target[m]) > e) { | |
288 anyDiffer = true; | |
289 testFailed(failureMessage + "; should be " + toString(target
) + ", was " + toString(source)); | |
290 break; | |
291 } | |
292 } | |
293 } | |
294 if (!anyDiffer) { | |
295 testPassed(successMessage); | |
296 } | |
297 }; | |
298 | |
299 function setupBuffers(tl, tr, bl, br) { | |
300 gl.bindBuffer(gl.ARRAY_BUFFER, quadParameters[0]); | |
301 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ | |
302 1.0, 1.0, tr, | |
303 -1.0, 1.0, tl, | |
304 -1.0, -1.0, bl, | |
305 1.0, 1.0, tr, | |
306 -1.0, -1.0, bl, | |
307 1.0, -1.0, br]), gl.STATIC_DRAW); | |
308 }; | |
309 | |
310 // Draw 1: (no variation) | |
311 setupBuffers(0.0, 0.0, 0.0, 0.0); | |
312 wtu.drawQuad(gl); | |
313 expectResult([0, 0, 0, 255], | |
314 "Draw 1 (no variation) returned the correct data", | |
315 "Draw 1 (no variation) returned incorrect data"); | |
316 | |
317 // Draw 2: (variation in x) | |
318 setupBuffers(1.0, 0.0, 1.0, 0.0); | |
319 wtu.drawQuad(gl); | |
320 expectResult([5, 0, 5, 255], | |
321 "Draw 2 (variation in x) returned the correct data", | |
322 "Draw 2 (variation in x) returned incorrect data"); | |
323 | |
324 // Draw 3: (variation in y) | |
325 setupBuffers(1.0, 1.0, 0.0, 0.0); | |
326 wtu.drawQuad(gl); | |
327 expectResult([0, 5, 5, 255], | |
328 "Draw 3 (variation in y) returned the correct data", | |
329 "Draw 3 (variation in y) returned incorrect data"); | |
330 | |
331 // Draw 4: (variation in x & y) | |
332 setupBuffers(1.0, 0.5, 0.5, 0.0); | |
333 wtu.drawQuad(gl); | |
334 expectResult([3, 3, 5, 255], | |
335 "Draw 4 (variation in x & y) returned the correct data", | |
336 "Draw 4 (variation in x & y) returned incorrect data"); | |
337 | |
338 } | |
339 | |
340 function attemptToForceGC() | |
341 { | |
342 var holderArray = []; | |
343 var tempArray; | |
344 window.tempArray = holderArray; | |
345 for (var i = 0; i < 12; ++i) { | |
346 tempArray = []; | |
347 for (var j = 0; j < 1024 * 1024; ++j) { | |
348 tempArray.push(0); | |
349 } | |
350 holderArray.push(tempArray); | |
351 } | |
352 window.tempArray = null; | |
353 } | |
354 | |
355 function runUniqueObjectTest() | |
356 { | |
357 debug("Testing that getExtension() returns the same object each time"); | |
358 gl.getExtension("OES_standard_derivatives").myProperty = 2; | |
359 if (window.GCController) { | |
360 window.GCController.collect(); | |
361 } else { | |
362 attemptToForceGC(); | |
363 } | |
364 shouldBe('gl.getExtension("OES_standard_derivatives").myProperty', '2'); | |
365 } | |
366 | |
367 | |
368 debug(""); | |
369 successfullyParsed = true; | |
370 </script> | |
371 <script src="../resources/js-test-post.js"></script> | |
372 <script> | |
373 </script> | |
374 | |
375 </body> | |
376 </html> | |
OLD | NEW |