From dac44623ee2488e43e9718bf4bc1fde76f1d9c9f Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Fri, 19 Jun 2015 15:47:22 -0700 Subject: [PATCH 1/3] [Plot] Begin adding WebGL fallback Begin adding code to handle case where WebGL context is lost, WTD-475. --- platform/features/plot/src/MCTChart.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/platform/features/plot/src/MCTChart.js b/platform/features/plot/src/MCTChart.js index b8350e9171..d07eb398aa 100644 --- a/platform/features/plot/src/MCTChart.js +++ b/platform/features/plot/src/MCTChart.js @@ -155,6 +155,15 @@ define( } } + function fallbackFromWebGL() { + element.html(TEMPLATE); + canvas = element.find("canvas")[0]; + chart = getChart([Canvas2DChart], canvas); + if (chart) { + doDraw(scope.draw); + } + } + // Try to initialize a chart. chart = getChart([GLChart, Canvas2DChart], canvas); @@ -192,4 +201,4 @@ define( return MCTChart; } -); \ No newline at end of file +); From b6fdf4d6ab815718d3e3210a0947f25850f1df52 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Fri, 19 Jun 2015 16:02:52 -0700 Subject: [PATCH 2/3] [Plot] Fall back from WebGL on context loss When a WebGL context is loss, fall back to displaying plots using regular canvas 2d API. WTD-475. --- platform/features/plot/src/MCTChart.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/platform/features/plot/src/MCTChart.js b/platform/features/plot/src/MCTChart.js index d07eb398aa..2ca51b2309 100644 --- a/platform/features/plot/src/MCTChart.js +++ b/platform/features/plot/src/MCTChart.js @@ -155,6 +155,7 @@ define( } } + // Switch from WebGL to plain 2D if context is lost function fallbackFromWebGL() { element.html(TEMPLATE); canvas = element.find("canvas")[0]; @@ -173,6 +174,11 @@ define( return; } + // WebGL is a bit of a special case; it may work, then fail + // later for various reasons, so we need to listen for this + // and fall back to plain canvas drawing when it occurs. + canvas.addEventListener("webglcontextlost", fallbackFromWebGL); + // Check for resize, on a timer activeInterval = $interval(drawIfResized, 1000); From 5ca954deafa9bd11655a8494c3e36fd6e402559a Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Fri, 19 Jun 2015 16:14:49 -0700 Subject: [PATCH 3/3] [Plot] Test fallback on webglcontextlost Add test case to verify that fallback occurs when a WebGL context is lost, WTD-475. --- platform/features/plot/test/MCTChartSpec.js | 22 +++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/platform/features/plot/test/MCTChartSpec.js b/platform/features/plot/test/MCTChartSpec.js index 93be797114..9c60b034a6 100644 --- a/platform/features/plot/test/MCTChartSpec.js +++ b/platform/features/plot/test/MCTChartSpec.js @@ -36,6 +36,7 @@ define( mockElement, mockCanvas, mockGL, + mockC2d, mockPromise, mctChart; @@ -47,13 +48,14 @@ define( mockScope = jasmine.createSpyObj("$scope", ["$watchCollection", "$on"]); mockElement = - jasmine.createSpyObj("element", ["find"]); + jasmine.createSpyObj("element", ["find", "html"]); mockInterval.cancel = jasmine.createSpy("cancelInterval"); mockPromise = jasmine.createSpyObj("promise", ["then"]); // mct-chart uses GLChart, so it needs WebGL API - mockCanvas = jasmine.createSpyObj("canvas", [ "getContext" ]); + mockCanvas = + jasmine.createSpyObj("canvas", [ "getContext", "addEventListener" ]); mockGL = jasmine.createSpyObj( "gl", [ @@ -81,6 +83,7 @@ define( "drawArrays" ] ); + mockC2d = jasmine.createSpyObj('c2d', ['clearRect']); mockGL.ARRAY_BUFFER = "ARRAY_BUFFER"; mockGL.DYNAMIC_DRAW = "DYNAMIC_DRAW"; mockGL.TRIANGLE_FAN = "TRIANGLE_FAN"; @@ -93,7 +96,9 @@ define( }); mockElement.find.andReturn([mockCanvas]); - mockCanvas.getContext.andReturn(mockGL); + mockCanvas.getContext.andCallFake(function (type) { + return { webgl: mockGL, '2d': mockC2d }[type]; + }); mockInterval.andReturn(mockPromise); mctChart = new MCTChart(mockInterval, mockLog); @@ -169,6 +174,15 @@ define( expect(mockLog.warn).toHaveBeenCalled(); }); + it("falls back to Canvas 2d API if WebGL context is lost", function () { + mctChart.link(mockScope, mockElement); + expect(mockCanvas.addEventListener) + .toHaveBeenCalledWith("webglcontextlost", jasmine.any(Function)); + expect(mockCanvas.getContext).not.toHaveBeenCalledWith('2d'); + mockCanvas.addEventListener.mostRecentCall.args[1](); + expect(mockCanvas.getContext).toHaveBeenCalledWith('2d'); + }); + it("logs nothing in nominal situations (WebGL available)", function () { // Complement the previous test mctChart.link(mockScope, mockElement); @@ -197,4 +211,4 @@ define( }); } -); \ No newline at end of file +);