content/canvas/test/webgl-conformance/conformance/extensions/oes-standard-derivatives.html

Wed, 31 Dec 2014 07:53:36 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:53:36 +0100
branch
TOR_BUG_3246
changeset 5
4ab42b5ab56c
permissions
-rw-r--r--

Correct small whitespace inconsistency, lost while renaming variables.

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

mercurial