Diff
Modified: trunk/LayoutTests/ChangeLog (127451 => 127452)
--- trunk/LayoutTests/ChangeLog 2012-09-04 09:25:24 UTC (rev 127451)
+++ trunk/LayoutTests/ChangeLog 2012-09-04 09:37:41 UTC (rev 127452)
@@ -1,3 +1,19 @@
+2012-09-04 Andrey Adaikin <aand...@chromium.org>
+
+ Web Inspector: [WebGL] Save gl.getError() status before taking a WebGL state snapshot and restore it afterwards
+ https://bugs.webkit.org/show_bug.cgi?id=95443
+
+ Reviewed by Vsevolod Vlasov.
+
+ Adds a test to check that we properly save the WebGL getError() status while doing the instrumentation.
+
+ * inspector/profiler/webgl/webgl-profiler-get-error-expected.txt: Added.
+ * inspector/profiler/webgl/webgl-profiler-get-error.html: Added.
+ * inspector/profiler/webgl/webgl-profiler-test.js: Added.
+ (initialize_WebGLProfilerTest.InspectorTest.enableWebGLAgent):
+ (initialize_WebGLProfilerTest):
+ (createWebGLContext):
+
2012-09-04 Alexander Pavlov <apav...@chromium.org>
Web Inspector: More directional control characters for debugging in inspector
Added: trunk/LayoutTests/inspector/profiler/webgl/webgl-profiler-get-error-expected.txt (0 => 127452)
--- trunk/LayoutTests/inspector/profiler/webgl/webgl-profiler-get-error-expected.txt (rev 0)
+++ trunk/LayoutTests/inspector/profiler/webgl/webgl-profiler-get-error-expected.txt 2012-09-04 09:37:41 UTC (rev 127452)
@@ -0,0 +1,3 @@
+Tests WebGL getError() status.
+
+Bug 95443
Added: trunk/LayoutTests/inspector/profiler/webgl/webgl-profiler-get-error.html (0 => 127452)
--- trunk/LayoutTests/inspector/profiler/webgl/webgl-profiler-get-error.html (rev 0)
+++ trunk/LayoutTests/inspector/profiler/webgl/webgl-profiler-get-error.html 2012-09-04 09:37:41 UTC (rev 127452)
@@ -0,0 +1,140 @@
+<html>
+<head>
+ <script src=""
+ <script src=""
+<script>
+
+var gl;
+var rawGL;
+var glResource;
+
+function assertNoErrors(gl)
+{
+ console.assert(gl.getError() === gl.NO_ERROR, "No GL error was expected at this time");
+}
+
+function assertEqualArrays(a, b)
+{
+ console.assert(a.length === b.length, "assertEqualArrays: a.length=" + a.length + ", b.length=" + b.length);
+ a = a.slice();
+ b = b.slice();
+ a.sort();
+ b.sort();
+ a.forEach(function(element, index) {
+ console.assert(a[index] === b[index], "assertEqualArrays: different values at index " + index);
+ });
+}
+
+function generateWebGLError(gl, error)
+{
+ switch (error) {
+ case gl.INVALID_ENUM:
+ gl.pixelStorei(123, 234);
+ break;
+ case gl.INVALID_VALUE:
+ gl.pixelStorei(gl.PACK_ALIGNMENT, 234);
+ break;
+ case gl.INVALID_OPERATION:
+ default:
+ gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
+ break;
+ }
+}
+
+function getAllErrors(gl)
+{
+ var errors = [];
+ while (true) {
+ var error = gl.getError();
+ if (error === gl.NO_ERROR)
+ break;
+ console.assert(typeof error === "number", "getError() should return a number instead of a " + (typeof error));
+ errors.push(error);
+ }
+ return errors;
+}
+
+function createAndRunWebGLProgram()
+{
+ gl = createWebGLContext();
+ console.assert(gl, "Failed to create WebGL context");
+
+ glResource = gl["__resourceObject"];
+ console.assert(glResource, "WebGL context is not wrapped");
+
+ rawGL = glResource.wrappedObject();
+ console.assert(rawGL, "No raw WebGL context found");
+ console.assert(gl !== rawGL, "Proxy and RAW contexts should not be the same");
+
+ assertNoErrors(gl);
+ assertNoErrors(rawGL);
+
+ // 1) Generate errors directly on the RAW context
+ // 2) Pick them via proxy.
+ var errors = [rawGL.INVALID_ENUM, rawGL.INVALID_VALUE, rawGL.INVALID_OPERATION];
+ errors.forEach(generateWebGLError.bind(this, rawGL));
+ assertEqualArrays(errors, getAllErrors(gl));
+ assertNoErrors(gl);
+ assertNoErrors(rawGL);
+
+ // 1) Generate errors on RAW context
+ // 2) Convert Resource to a Replayable => this should clean up the RAW context and save the errors in proxy
+ // 3) Check that RAW context no longer have errors
+ // 4) Check that proxy still has the original errors saved
+ var errors = [rawGL.INVALID_ENUM, rawGL.INVALID_VALUE, rawGL.INVALID_OPERATION];
+ errors.forEach(generateWebGLError.bind(this, rawGL));
+ var cache = {
+ put: function() {},
+ get: function() {}
+ };
+ glResource.toReplayable(cache);
+ assertNoErrors(rawGL);
+ assertEqualArrays(errors, getAllErrors(gl));
+ assertNoErrors(gl);
+
+ // 1) Repeat 1-3 steps from the above
+ // 2) Check proxy and RAW errors interleaved
+ var errors = [rawGL.INVALID_ENUM, rawGL.INVALID_VALUE, rawGL.INVALID_OPERATION];
+ errors.forEach(generateWebGLError.bind(this, rawGL));
+ var cache = {
+ put: function() {},
+ get: function() {}
+ };
+ glResource.toReplayable(cache);
+ assertNoErrors(rawGL);
+
+ var value = gl.getError();
+ console.assert(typeof value === "number", "getError() should return a number instead of a " + (typeof value));
+ console.assert(value !== gl.NO_ERROR, "An error was expected");
+ errors.forEach(generateWebGLError.bind(this, rawGL)); // Generate again in the RAW context.
+ // Now we "have" 2 errors left in the proxy and 3 new errors in the RAW context => should return 3 errors from the proxy.
+ assertEqualArrays(errors, getAllErrors(gl));
+ assertNoErrors(gl);
+ assertNoErrors(rawGL);
+
+ return "SUCCESS";
+}
+
+function test()
+{
+ InspectorTest.enableWebGLAgent(step1);
+ function step1()
+ {
+ InspectorTest.evaluateInConsole("createAndRunWebGLProgram()", step2);
+ }
+ function step2(error)
+ {
+ InspectorTest.assertEquals("\"SUCCESS\"", error);
+ InspectorTest.completeTest();
+ }
+}
+
+</script>
+</head>
+<body _onload_="runTest()">
+<p>
+Tests WebGL getError() status.
+</p>
+<a href="" 95443</a>
+</body>
+</html>
Added: trunk/LayoutTests/inspector/profiler/webgl/webgl-profiler-test.js (0 => 127452)
--- trunk/LayoutTests/inspector/profiler/webgl/webgl-profiler-test.js (rev 0)
+++ trunk/LayoutTests/inspector/profiler/webgl/webgl-profiler-test.js 2012-09-04 09:37:41 UTC (rev 127452)
@@ -0,0 +1,37 @@
+var initialize_WebGLProfilerTest = function() {
+
+InspectorTest.enableWebGLAgent = function(callback)
+{
+ function webGLAgentEnabled(error)
+ {
+ if (!error)
+ InspectorTest.safeWrap(callback)();
+ else {
+ InspectorTest.addResult("FAILED to enable WebGLAgent: " + error);
+ InspectorTest.completeTest();
+ }
+ }
+ try {
+ WebGLAgent.enable(webGLAgentEnabled);
+ } catch (e) {
+ InspectorTest.addResult("Exception while enabling WebGLAgent", e);
+ InspectorTest.completeTest();
+ }
+};
+
+};
+
+function createWebGLContext(opt_canvas)
+{
+ var canvas = opt_canvas || document.createElement("canvas");
+ var contextIds = ["experimental-webgl", "webkit-3d", "3d"];
+ for (var i = 0, contextId; contextId = contextIds[i]; ++i) {
+ var gl = canvas.getContext(contextId);
+ if (gl)
+ return gl;
+ }
+ return null;
+}
+
+if (window.testRunner)
+ testRunner.overridePreference("WebKitWebGLEnabled", "1");
Modified: trunk/Source/WebCore/ChangeLog (127451 => 127452)
--- trunk/Source/WebCore/ChangeLog 2012-09-04 09:25:24 UTC (rev 127451)
+++ trunk/Source/WebCore/ChangeLog 2012-09-04 09:37:41 UTC (rev 127452)
@@ -1,3 +1,15 @@
+2012-09-04 Andrey Adaikin <aand...@chromium.org>
+
+ Web Inspector: [WebGL] Save gl.getError() status before taking a WebGL state snapshot and restore it afterwards
+ https://bugs.webkit.org/show_bug.cgi?id=95443
+
+ Reviewed by Vsevolod Vlasov.
+
+ Save gl.getError() status before taking the GL snapshot and restore it afterwards.
+
+ * inspector/InjectedScriptWebGLModuleSource.js:
+ (.):
+
2012-09-04 Alexander Pavlov <apav...@chromium.org>
Web Inspector: More directional control characters for debugging in inspector
Modified: trunk/Source/WebCore/inspector/InjectedScriptWebGLModuleSource.js (127451 => 127452)
--- trunk/Source/WebCore/inspector/InjectedScriptWebGLModuleSource.js 2012-09-04 09:25:24 UTC (rev 127451)
+++ trunk/Source/WebCore/inspector/InjectedScriptWebGLModuleSource.js 2012-09-04 09:37:41 UTC (rev 127452)
@@ -339,6 +339,14 @@
this._stackTrace = stackTrace;
},
+ /**
+ * @param {*} result
+ */
+ setResult: function(result)
+ {
+ this._result = result;
+ },
+
freeze: function()
{
if (this._freezed)
@@ -895,6 +903,8 @@
var gl = glResource.wrappedObject();
var program = this.wrappedObject();
+ var originalErrors = glResource.getAllErrors();
+
var uniforms = [];
var uniformsCount = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
for (var i = 0; i < uniformsCount; ++i) {
@@ -912,6 +922,8 @@
});
}
data.uniforms = uniforms;
+
+ glResource.restoreErrors(originalErrors);
},
/**
@@ -1215,6 +1227,79 @@
},
/**
+ * @return {Array.<number>}
+ */
+ getAllErrors: function()
+ {
+ var errors = [];
+ var gl = this.wrappedObject();
+ if (gl) {
+ while (true) {
+ var error = gl.getError();
+ if (error === gl.NO_ERROR)
+ break;
+ this.clearError(error);
+ errors.push(error);
+ }
+ }
+ if (this._customErrors) {
+ for (var key in this._customErrors) {
+ var error = Number(key);
+ errors.push(error);
+ }
+ delete this._customErrors;
+ }
+ return errors;
+ },
+
+ /**
+ * @param {Array.<number>} errors
+ */
+ restoreErrors: function(errors)
+ {
+ var gl = this.wrappedObject();
+ if (gl) {
+ var wasError = false;
+ while (gl.getError() !== gl.NO_ERROR)
+ wasError = true;
+ console.assert(!wasError, "Error(s) while capturing current WebGL state.");
+ }
+ if (!errors.length)
+ delete this._customErrors;
+ else {
+ this._customErrors = {};
+ for (var i = 0, n = errors.length; i < n; ++i)
+ this._customErrors[errors[i]] = true;
+ }
+ },
+
+ /**
+ * @param {number} error
+ */
+ clearError: function(error)
+ {
+ if (this._customErrors)
+ delete this._customErrors[error];
+ },
+
+ /**
+ * @return {number}
+ */
+ nextError: function()
+ {
+ if (this._customErrors) {
+ for (var key in this._customErrors) {
+ var error = Number(key);
+ delete this._customErrors[error];
+ return error;
+ }
+ }
+ delete this._customErrors;
+ var gl = this.wrappedObject();
+ return gl ? gl.NO_ERROR : 0;
+ },
+
+ /**
* @override
* @param {Object} data
* @param {Cache} cache
@@ -1224,7 +1309,7 @@
var gl = this.wrappedObject();
data.replayContextCallback = this._replayContextCallback;
- // FIXME: Save the getError() status and restore it after taking the GL state snapshot.
+ var originalErrors = this.getAllErrors();
// Take a full GL state snapshot.
var glState = {};
@@ -1233,7 +1318,6 @@
});
WebGLRenderingContextResource.StateParameters.forEach(function(parameter) {
glState[parameter] = Resource.toReplayable(gl.getParameter(gl[parameter]), cache);
- // FIXME: Call while(gl.getError() != gl.NO_ERROR) {...} to check if a particular parameter is supported.
});
// VERTEX_ATTRIB_ARRAYS
@@ -1266,6 +1350,8 @@
gl.activeTexture(currentTextureBinding);
data.glState = glState;
+
+ this.restoreErrors(originalErrors);
},
/**
@@ -1546,6 +1632,16 @@
if (!this._call)
this._call = new Call(this._glResource, this._functionName, this._args, this.result());
return this._call;
+ },
+
+ /**
+ * @param {*} result
+ */
+ _overrideResult: function(result)
+ {
+ var call = this.call();
+ call.setResult(result);
+ this._result = result;
}
}
@@ -1627,6 +1723,20 @@
customWrapFunction("framebufferTexture2D");
customWrapFunction("renderbufferStorage");
+ /** @this WebGLRenderingContextResource.WrapFunction */
+ wrapFunctions["getError"] = function()
+ {
+ var gl = this._originalObject;
+ var error = this.result();
+ if (error !== gl.NO_ERROR)
+ this._glResource.clearError(error);
+ else {
+ error = this._glResource.nextError();
+ if (error !== gl.NO_ERROR)
+ this._overrideResult(error);
+ }
+ }
+
WebGLRenderingContextResource._wrapFunctions = wrapFunctions;
}
return wrapFunctions;