Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(45)

Side by Side Diff: third_party/webgl/sdk/debug/webgl-debug.js

Issue 9360034: Remove everthing except conformance tests in the deps/third_party/webgl (Closed) Base URL: svn://chrome-svn/chrome/trunk/deps/
Patch Set: Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 //Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 //Use of this source code is governed by a BSD-style license that can be
3 //found in the LICENSE file.
4
5 // Various functions for helping debug WebGL apps.
6
7 WebGLDebugUtils = function() {
8
9 /**
10 * Wrapped logging function.
11 * @param {string} msg Message to log.
12 */
13 var log = function(msg) {
14 if (window.console && window.console.log) {
15 window.console.log(msg);
16 }
17 };
18
19 /**
20 * Which arguements are enums.
21 * @type {!Object.<number, string>}
22 */
23 var glValidEnumContexts = {
24
25 // Generic setters and getters
26
27 'enable': { 0:true },
28 'disable': { 0:true },
29 'getParameter': { 0:true },
30
31 // Rendering
32
33 'drawArrays': { 0:true },
34 'drawElements': { 0:true, 2:true },
35
36 // Shaders
37
38 'createShader': { 0:true },
39 'getShaderParameter': { 1:true },
40 'getProgramParameter': { 1:true },
41
42 // Vertex attributes
43
44 'getVertexAttrib': { 1:true },
45 'vertexAttribPointer': { 2:true },
46
47 // Textures
48
49 'bindTexture': { 0:true },
50 'activeTexture': { 0:true },
51 'getTexParameter': { 0:true, 1:true },
52 'texParameterf': { 0:true, 1:true },
53 'texParameteri': { 0:true, 1:true, 2:true },
54 'texImage2D': { 0:true, 2:true, 6:true, 7:true },
55 'texSubImage2D': { 0:true, 6:true, 7:true },
56 'copyTexImage2D': { 0:true, 2:true },
57 'copyTexSubImage2D': { 0:true },
58 'generateMipmap': { 0:true },
59
60 // Buffer objects
61
62 'bindBuffer': { 0:true },
63 'bufferData': { 0:true, 2:true },
64 'bufferSubData': { 0:true },
65 'getBufferParameter': { 0:true, 1:true },
66
67 // Renderbuffers and framebuffers
68
69 'pixelStorei': { 0:true, 1:true },
70 'readPixels': { 4:true, 5:true },
71 'bindRenderbuffer': { 0:true },
72 'bindFramebuffer': { 0:true },
73 'checkFramebufferStatus': { 0:true },
74 'framebufferRenderbuffer': { 0:true, 1:true, 2:true },
75 'framebufferTexture2D': { 0:true, 1:true, 2:true },
76 'getFramebufferAttachmentParameter': { 0:true, 1:true, 2:true },
77 'getRenderbufferParameter': { 0:true, 1:true },
78 'renderbufferStorage': { 0:true, 1:true },
79
80 // Frame buffer operations (clear, blend, depth test, stencil)
81
82 'clear': { 0:true },
83 'depthFunc': { 0:true },
84 'blendFunc': { 0:true, 1:true },
85 'blendFuncSeparate': { 0:true, 1:true, 2:true, 3:true },
86 'blendEquation': { 0:true },
87 'blendEquationSeparate': { 0:true, 1:true },
88 'stencilFunc': { 0:true },
89 'stencilFuncSeparate': { 0:true, 1:true },
90 'stencilMaskSeparate': { 0:true },
91 'stencilOp': { 0:true, 1:true, 2:true },
92 'stencilOpSeparate': { 0:true, 1:true, 2:true, 3:true },
93
94 // Culling
95
96 'cullFace': { 0:true },
97 'frontFace': { 0:true },
98 };
99
100 /**
101 * Map of numbers to names.
102 * @type {Object}
103 */
104 var glEnums = null;
105
106 /**
107 * Initializes this module. Safe to call more than once.
108 * @param {!WebGLRenderingContext} ctx A WebGL context. If
109 * you have more than one context it doesn't matter which one
110 * you pass in, it is only used to pull out constants.
111 */
112 function init(ctx) {
113 if (glEnums == null) {
114 glEnums = { };
115 for (var propertyName in ctx) {
116 if (typeof ctx[propertyName] == 'number') {
117 glEnums[ctx[propertyName]] = propertyName;
118 }
119 }
120 }
121 }
122
123 /**
124 * Checks the utils have been initialized.
125 */
126 function checkInit() {
127 if (glEnums == null) {
128 throw 'WebGLDebugUtils.init(ctx) not called';
129 }
130 }
131
132 /**
133 * Returns true or false if value matches any WebGL enum
134 * @param {*} value Value to check if it might be an enum.
135 * @return {boolean} True if value matches one of the WebGL defined enums
136 */
137 function mightBeEnum(value) {
138 checkInit();
139 return (glEnums[value] !== undefined);
140 }
141
142 /**
143 * Gets an string version of an WebGL enum.
144 *
145 * Example:
146 * var str = WebGLDebugUtil.glEnumToString(ctx.getError());
147 *
148 * @param {number} value Value to return an enum for
149 * @return {string} The string version of the enum.
150 */
151 function glEnumToString(value) {
152 checkInit();
153 var name = glEnums[value];
154 return (name !== undefined) ? name :
155 ("*UNKNOWN WebGL ENUM (0x" + value.toString(16) + ")");
156 }
157
158 /**
159 * Returns the string version of a WebGL argument.
160 * Attempts to convert enum arguments to strings.
161 * @param {string} functionName the name of the WebGL function.
162 * @param {number} argumentIndx the index of the argument.
163 * @param {*} value The value of the argument.
164 * @return {string} The value as a string.
165 */
166 function glFunctionArgToString(functionName, argumentIndex, value) {
167 var funcInfo = glValidEnumContexts[functionName];
168 if (funcInfo !== undefined) {
169 if (funcInfo[argumentIndex]) {
170 return glEnumToString(value);
171 }
172 }
173 return value.toString();
174 }
175
176 /**
177 * Given a WebGL context returns a wrapped context that calls
178 * gl.getError after every command and calls a function if the
179 * result is not gl.NO_ERROR.
180 *
181 * @param {!WebGLRenderingContext} ctx The webgl context to
182 * wrap.
183 * @param {!function(err, funcName, args): void} opt_onErrorFunc
184 * The function to call when gl.getError returns an
185 * error. If not specified the default function calls
186 * console.log with a message.
187 */
188 function makeDebugContext(ctx, opt_onErrorFunc) {
189 init(ctx);
190 opt_onErrorFunc = opt_onErrorFunc || function(err, functionName, args) {
191 // apparently we can't do args.join(",");
192 var argStr = "";
193 for (var ii = 0; ii < args.length; ++ii) {
194 argStr += ((ii == 0) ? '' : ', ') +
195 glFunctionArgToString(functionName, ii, args[ii]);
196 }
197 log("WebGL error "+ glEnumToString(err) + " in "+ functionName +
198 "(" + argStr + ")");
199 };
200
201 // Holds booleans for each GL error so after we get the error ourselves
202 // we can still return it to the client app.
203 var glErrorShadow = { };
204
205 // Makes a function that calls a WebGL function and then calls getError.
206 function makeErrorWrapper(ctx, functionName) {
207 return function() {
208 var result = ctx[functionName].apply(ctx, arguments);
209 var err = ctx.getError();
210 if (err != 0) {
211 glErrorShadow[err] = true;
212 opt_onErrorFunc(err, functionName, arguments);
213 }
214 return result;
215 };
216 }
217
218 // Make a an object that has a copy of every property of the WebGL context
219 // but wraps all functions.
220 var wrapper = {};
221 for (var propertyName in ctx) {
222 if (typeof ctx[propertyName] == 'function') {
223 wrapper[propertyName] = makeErrorWrapper(ctx, propertyName);
224 } else {
225 wrapper[propertyName] = ctx[propertyName];
226 }
227 }
228
229 // Override the getError function with one that returns our saved results.
230 wrapper.getError = function() {
231 for (var err in glErrorShadow) {
232 if (glErrorShadow[err]) {
233 glErrorShadow[err] = false;
234 return err;
235 }
236 }
237 return ctx.NO_ERROR;
238 };
239
240 return wrapper;
241 }
242
243 function resetToInitialState(ctx) {
244 var numAttribs = ctx.getParameter(ctx.MAX_VERTEX_ATTRIBS);
245 var tmp = ctx.createBuffer();
246 ctx.bindBuffer(ctx.ARRAY_BUFFER, tmp);
247 for (var ii = 0; ii < numAttribs; ++ii) {
248 ctx.disableVertexAttribArray(ii);
249 ctx.vertexAttribPointer(ii, 4, ctx.FLOAT, false, 0, 0);
250 ctx.vertexAttrib1f(ii, 0);
251 }
252 ctx.deleteBuffer(tmp);
253
254 var numTextureUnits = ctx.getParameter(ctx.MAX_TEXTURE_IMAGE_UNITS);
255 for (var ii = 0; ii < numTextureUnits; ++ii) {
256 ctx.activeTexture(ctx.TEXTURE0 + ii);
257 ctx.bindTexture(ctx.TEXTURE_CUBE_MAP, null);
258 ctx.bindTexture(ctx.TEXTURE_2D, null);
259 }
260
261 ctx.activeTexture(ctx.TEXTURE0);
262 ctx.useProgram(null);
263 ctx.bindBuffer(ctx.ARRAY_BUFFER, null);
264 ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, null);
265 ctx.bindFramebuffer(ctx.FRAMEBUFFER, null);
266 ctx.bindRenderbuffer(ctx.RENDERBUFFER, null);
267 ctx.disable(ctx.BLEND);
268 ctx.disable(ctx.CULL_FACE);
269 ctx.disable(ctx.DEPTH_TEST);
270 ctx.disable(ctx.DITHER);
271 ctx.disable(ctx.SCISSOR_TEST);
272 ctx.blendColor(0, 0, 0, 0);
273 ctx.blendEquation(ctx.FUNC_ADD);
274 ctx.blendFunc(ctx.ONE, ctx.ZERO);
275 ctx.clearColor(0, 0, 0, 0);
276 ctx.clearDepth(1);
277 ctx.clearStencil(-1);
278 ctx.colorMask(true, true, true, true);
279 ctx.cullFace(ctx.BACK);
280 ctx.depthFunc(ctx.LESS);
281 ctx.depthMask(true);
282 ctx.depthRange(0, 1);
283 ctx.frontFace(ctx.CCW);
284 ctx.hint(ctx.GENERATE_MIPMAP_HINT, ctx.DONT_CARE);
285 ctx.lineWidth(1);
286 ctx.pixelStorei(ctx.PACK_ALIGNMENT, 4);
287 ctx.pixelStorei(ctx.UNPACK_ALIGNMENT, 4);
288 ctx.pixelStorei(ctx.UNPACK_FLIP_Y_WEBGL, false);
289 ctx.pixelStorei(ctx.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
290 // TODO: Delete this IF.
291 if (ctx.UNPACK_COLORSPACE_CONVERSION_WEBGL) {
292 ctx.pixelStorei(ctx.UNPACK_COLORSPACE_CONVERSION_WEBGL, ctx.BROWSER_DEFAULT_ WEBGL);
293 }
294 ctx.polygonOffset(0, 0);
295 ctx.sampleCoverage(1, false);
296 ctx.scissor(0, 0, ctx.canvas.width, ctx.canvas.height);
297 ctx.stencilFunc(ctx.ALWAYS, 0, 0xFFFFFFFF);
298 ctx.stencilMask(0xFFFFFFFF);
299 ctx.stencilOp(ctx.KEEP, ctx.KEEP, ctx.KEEP);
300 ctx.viewport(0, 0, ctx.canvas.clientWidth, ctx.canvas.clientHeight);
301 ctx.clear(ctx.COLOR_BUFFER_BIT | ctx.DEPTH_BUFFER_BIT | ctx.STENCIL_BUFFER_BIT );
302
303 // TODO: This should NOT be needed but Firefox fails with 'hint'
304 while(ctx.getError());
305 }
306
307 function makeLostContextSimulatingContext(ctx) {
308 var wrapper_ = {};
309 var contextId_ = 1;
310 var contextLost_ = false;
311 var resourceId_ = 0;
312 var resourceDb_ = [];
313 var onLost_ = undefined;
314 var onRestored_ = undefined;
315 var nextOnRestored_ = undefined;
316
317 // Holds booleans for each GL error so can simulate errors.
318 var glErrorShadow_ = { };
319
320 function isWebGLObject(obj) {
321 //return false;
322 return (obj instanceof WebGLBuffer ||
323 obj instanceof WebGLFramebuffer ||
324 obj instanceof WebGLProgram ||
325 obj instanceof WebGLRenderbuffer ||
326 obj instanceof WebGLShader ||
327 obj instanceof WebGLTexture);
328 }
329
330 function checkResources(args) {
331 for (var ii = 0; ii < args.length; ++ii) {
332 var arg = args[ii];
333 if (isWebGLObject(arg)) {
334 return arg.__webglDebugContextLostId__ == contextId_;
335 }
336 }
337 return true;
338 }
339
340 function clearErrors() {
341 var k = Object.keys(glErrorShadow_);
342 for (var ii = 0; ii < k.length; ++ii) {
343 delete glErrorShdow_[k];
344 }
345 }
346
347 // Makes a function that simulates WebGL when out of context.
348 function makeLostContextWrapper(ctx, functionName) {
349 var f = ctx[functionName];
350 return function() {
351 // Only call the functions if the context is not lost.
352 if (!contextLost_) {
353 if (!checkResources(arguments)) {
354 glErrorShadow_[ctx.INVALID_OPERATION] = true;
355 return;
356 }
357 var result = f.apply(ctx, arguments);
358 return result;
359 }
360 };
361 }
362
363 for (var propertyName in ctx) {
364 if (typeof ctx[propertyName] == 'function') {
365 wrapper_[propertyName] = makeLostContextWrapper(ctx, propertyName);
366 } else {
367 wrapper_[propertyName] = ctx[propertyName];
368 }
369 }
370
371 function makeWebGLContextEvent(statusMessage) {
372 return {statusMessage: statusMessage};
373 }
374
375 function freeResources() {
376 for (var ii = 0; ii < resourceDb_.length; ++ii) {
377 var resource = resourceDb_[ii];
378 if (resource instanceof WebGLBuffer) {
379 ctx.deleteBuffer(resource);
380 } else if (resource instanceof WebctxFramebuffer) {
381 ctx.deleteFramebuffer(resource);
382 } else if (resource instanceof WebctxProgram) {
383 ctx.deleteProgram(resource);
384 } else if (resource instanceof WebctxRenderbuffer) {
385 ctx.deleteRenderbuffer(resource);
386 } else if (resource instanceof WebctxShader) {
387 ctx.deleteShader(resource);
388 } else if (resource instanceof WebctxTexture) {
389 ctx.deleteTexture(resource);
390 }
391 }
392 }
393
394 wrapper_.loseContext = function() {
395 if (!contextLost_) {
396 contextLost_ = true;
397 ++contextId_;
398 while (ctx.getError());
399 clearErrors();
400 glErrorShadow_[ctx.CONTEXT_LOST_WEBGL] = true;
401 setTimeout(function() {
402 if (onLost_) {
403 onLost_(makeWebGLContextEvent("context lost"));
404 }
405 }, 0);
406 }
407 };
408
409 wrapper_.restoreContext = function() {
410 if (contextLost_) {
411 if (onRestored_) {
412 setTimeout(function() {
413 freeResources();
414 resetToInitialState(ctx);
415 contextLost_ = false;
416 if (onRestored_) {
417 var callback = onRestored_;
418 onRestored_ = nextOnRestored_;
419 nextOnRestored_ = undefined;
420 callback(makeWebGLContextEvent("context restored"));
421 }
422 }, 0);
423 } else {
424 throw "You can not restore the context without a listener"
425 }
426 }
427 };
428
429 // Wrap a few functions specially.
430 wrapper_.getError = function() {
431 if (!contextLost_) {
432 var err;
433 while (err = ctx.getError()) {
434 glErrorShadow_[err] = true;
435 }
436 }
437 for (var err in glErrorShadow_) {
438 if (glErrorShadow_[err]) {
439 delete glErrorShadow_[err];
440 return err;
441 }
442 }
443 return ctx.NO_ERROR;
444 };
445
446 var creationFunctions = [
447 "createBuffer",
448 "createFramebuffer",
449 "createProgram",
450 "createRenderbuffer",
451 "createShader",
452 "createTexture"
453 ];
454 for (var ii = 0; ii < creationFunctions.length; ++ii) {
455 var functionName = creationFunctions[ii];
456 wrapper_[functionName] = function(f) {
457 return function() {
458 if (contextLost_) {
459 return null;
460 }
461 var obj = f.apply(ctx, arguments);
462 obj.__webglDebugContextLostId__ = contextId_;
463 resourceDb_.push(obj);
464 return obj;
465 };
466 }(ctx[functionName]);
467 }
468
469 var functionsThatShouldReturnNull = [
470 "getActiveAttrib",
471 "getActiveUniform",
472 "getBufferParameter",
473 "getContextAttributes",
474 "getAttachedShaders",
475 "getFramebufferAttachmentParameter",
476 "getParameter",
477 "getProgramParameter",
478 "getProgramInfoLog",
479 "getRenderbufferParameter",
480 "getShaderParameter",
481 "getShaderInfoLog",
482 "getShaderSource",
483 "getTexParameter",
484 "getUniform",
485 "getUniformLocation",
486 "getVertexAttrib"
487 ];
488 for (var ii = 0; ii < functionsThatShouldReturnNull.length; ++ii) {
489 var functionName = functionsThatShouldReturnNull[ii];
490 wrapper_[functionName] = function(f) {
491 return function() {
492 if (contextLost_) {
493 return null;
494 }
495 return f.apply(ctx, arguments);
496 }
497 }(wrapper_[functionName]);
498 }
499
500 var isFunctions = [
501 "isBuffer",
502 "isEnabled",
503 "isFramebuffer",
504 "isProgram",
505 "isRenderbuffer",
506 "isShader",
507 "isTexture"
508 ];
509 for (var ii = 0; ii < isFunctions.length; ++ii) {
510 var functionName = isFunctions[ii];
511 wrapper_[functionName] = function(f) {
512 return function() {
513 if (contextLost_) {
514 return false;
515 }
516 return f.apply(ctx, arguments);
517 }
518 }(wrapper_[functionName]);
519 }
520
521 wrapper_.checkFramebufferStatus = function(f) {
522 return function() {
523 if (contextLost_) {
524 return ctx.FRAMEBUFFER_UNSUPPORTED;
525 }
526 return f.apply(ctx, arguments);
527 };
528 }(wrapper_.checkFramebufferStatus);
529
530 wrapper_.getAttribLocation = function(f) {
531 return function() {
532 if (contextLost_) {
533 return -1;
534 }
535 return f.apply(ctx, arguments);
536 };
537 }(wrapper_.getAttribLocation);
538
539 wrapper_.getVertexAttribOffset = function(f) {
540 return function() {
541 if (contextLost_) {
542 return 0;
543 }
544 return f.apply(ctx, arguments);
545 };
546 }(wrapper_.getVertexAttribOffset);
547
548 wrapper_.isContextLost = function() {
549 return contextLost_;
550 };
551
552 function wrapEvent(listener) {
553 if (typeof(listener) == "function") {
554 return listener;
555 } else {
556 return function(info) {
557 listener.handleEvent(info);
558 }
559 }
560 }
561
562 wrapper_.registerOnContextLostListener = function(listener) {
563 onLost_ = wrapEvent(listener);
564 };
565
566 wrapper_.registerOnContextRestoredListener = function(listener) {
567 if (contextLost_) {
568 nextOnRestored_ = wrapEvent(listener);
569 } else {
570 onRestored_ = wrapEvent(listener);
571 }
572 }
573
574 return wrapper_;
575 }
576
577 return {
578 /**
579 * Initializes this module. Safe to call more than once.
580 * @param {!WebGLRenderingContext} ctx A WebGL context. If
581 * you have more than one context it doesn't matter which one
582 * you pass in, it is only used to pull out constants.
583 */
584 'init': init,
585
586 /**
587 * Returns true or false if value matches any WebGL enum
588 * @param {*} value Value to check if it might be an enum.
589 * @return {boolean} True if value matches one of the WebGL defined enums
590 */
591 'mightBeEnum': mightBeEnum,
592
593 /**
594 * Gets an string version of an WebGL enum.
595 *
596 * Example:
597 * WebGLDebugUtil.init(ctx);
598 * var str = WebGLDebugUtil.glEnumToString(ctx.getError());
599 *
600 * @param {number} value Value to return an enum for
601 * @return {string} The string version of the enum.
602 */
603 'glEnumToString': glEnumToString,
604
605 /**
606 * Converts the argument of a WebGL function to a string.
607 * Attempts to convert enum arguments to strings.
608 *
609 * Example:
610 * WebGLDebugUtil.init(ctx);
611 * var str = WebGLDebugUtil.glFunctionArgToString('bindTexture', 0, gl.TEXTU RE_2D);
612 *
613 * would return 'TEXTURE_2D'
614 *
615 * @param {string} functionName the name of the WebGL function.
616 * @param {number} argumentIndx the index of the argument.
617 * @param {*} value The value of the argument.
618 * @return {string} The value as a string.
619 */
620 'glFunctionArgToString': glFunctionArgToString,
621
622 /**
623 * Given a WebGL context returns a wrapped context that calls
624 * gl.getError after every command and calls a function if the
625 * result is not NO_ERROR.
626 *
627 * You can supply your own function if you want. For example, if you'd like
628 * an exception thrown on any GL error you could do this
629 *
630 * function throwOnGLError(err, funcName, args) {
631 * throw WebGLDebugUtils.glEnumToString(err) + " was caused by call to" +
632 * funcName;
633 * };
634 *
635 * ctx = WebGLDebugUtils.makeDebugContext(
636 * canvas.getContext("webgl"), throwOnGLError);
637 *
638 * @param {!WebGLRenderingContext} ctx The webgl context to wrap.
639 * @param {!function(err, funcName, args): void} opt_onErrorFunc The function
640 * to call when gl.getError returns an error. If not specified the default
641 * function calls console.log with a message.
642 */
643 'makeDebugContext': makeDebugContext,
644
645 /**
646 * Given a WebGL context returns a wrapped context that adds 4
647 * functions.
648 *
649 * ctx.loseContext:
650 * simulates a lost context event.
651 *
652 * ctx.restoreContext:
653 * simulates the context being restored.
654 *
655 * ctx.registerOnContextLostListener(listener):
656 * lets you register a listener for context lost. Use instead
657 * of addEventListener('webglcontextlostevent', listener);
658 *
659 * ctx.registerOnContextRestoredListener(listener):
660 * lets you register a listener for context restored. Use
661 * instead of addEventListener('webglcontextrestored',
662 * listener);
663 *
664 * @param {!WebGLRenderingContext} ctx The webgl context to wrap.
665 */
666 'makeLostContextSimulatingContext': makeLostContextSimulatingContext,
667
668 /**
669 * Resets a context to the initial state.
670 * @param {!WebGLRenderingContext} ctx The webgl context to
671 * reset.
672 */
673 'resetToInitialState': resetToInitialState
674 };
675
676 }();
677
OLDNEW
« no previous file with comments | « third_party/webgl/sdk/debug/lost-context-simulator-test.html ('k') | third_party/webgl/sdk/tests/00_test_list.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698