Commit 5744fb00 authored by Kenneth Russell's avatar Kenneth Russell Committed by Chromium LUCI CQ

Fix WebGL drawn to another 2D canvas after tab is backgrounded.

In this scenario, the WebGL canvas's ResourceProvider holds a copy of
the rendered content. This ResourceProvider is purged when the tab is
backgrounded, so ensure it is repopulated even if the canvas thinks
its state has not changed.

Thanks to Xing Xu from Intel for the original CL and test case.

Bug: 736969
Change-Id: Ib57a65f1fee2ab95099b335171034d83ce9ec29f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2639295
Commit-Queue: Kenneth Russell <kbr@chromium.org>
Reviewed-by: default avatarShrek Shao <shrekshao@google.com>
Cr-Commit-Position: refs/heads/master@{#845449}
parent 2d3ee649
<!DOCTYPE HTML>
<html>
<head>
<title>WebGL Test: WebGL Content Preserved after Tab Switched</title>
<style type="text/css">
.nomargin {
margin: 0px auto;
}
</style>
<script src="pixel_webgl_util.js"></script>
</head>
<body onload="main()">
<canvas id="source" width="100" height="100" class="nomargin"></canvas>
<canvas id="destination" width="100" height="100" class="nomargin"></canvas>
<!-- The pixel result of this test is two green squares side-by-side. -->
<script>
let canvasSource = document.getElementById("source");
let canvasDestination = document.getElementById("destination");
let canvasOptions = {
preserveDrawingBuffer: true
};
let destinationContext = canvasDestination.getContext("2d", canvasOptions);
let gl;
canvasSource.addEventListener("webglcontextlost", function(event) {
console.log('context lost');
event.preventDefault();
}, false);
canvasSource.addEventListener("webglcontextrestored", init3d, false);
function copyImageInternal() {
let error = gl.getError();
if (error) {
console.log('Gl Error: ' + error);
}
destinationContext.clearRect(0, 0, 100, 100);
destinationContext.drawImage(canvasSource, 0, 0);
}
function copyImage() {
copyImageInternal();
domAutomationController.send("SUCCESS");
}
function init3d() {
gl = canvasSource.getContext("webgl", canvasOptions);
if (gl == null)
console.log("couldn't get webgl context");
else
console.log(gl);
gl.viewport(0, 0, canvasSource.width, canvasSource.height);
gl.clearColor(0, 0.5, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
copyImageInternal();
}
function main() {
init3d();
if (gl) {
domAutomationController.send("READY");
} else {
domAutomationController.send("FAILURE");
}
}
</script>
</body>
</html>
......@@ -206,6 +206,18 @@ class PixelIntegrationTest(
dummy_tab.action_runner.Wait(2)
tab.Activate()
def _SwitchTabsAndCopyImage(self, tab, page):
del page # Unused in this particular action.
if not tab.browser.supports_tab_control:
self.fail('Browser must support tab control')
dummy_tab = tab.browser.tabs.New()
dummy_tab.Activate()
# Wait for 2 seconds so that new tab becomes visible.
dummy_tab.action_runner.Wait(2)
# Close new tab.
dummy_tab.Close()
tab.EvaluateJavaScript("copyImage()")
def _RunTestWithHighPerformanceTab(self, tab, page):
del page # Unused in this particular action.
if not self._IsDualGPUMacLaptop():
......
......@@ -330,6 +330,10 @@ class PixelTestPages(object):
base_name + '_OffscreenCanvasIBRCWebGLWorker',
test_rect=[0, 0, 300, 300],
optional_action='RunOffscreenCanvasIBRCWebGLTest'),
PixelTestPage('pixel_webgl_preserved_after_tab_switch.html',
base_name + '_WebGLPreservedAfterTabSwitch',
test_rect=[0, 0, 300, 300],
optional_action='SwitchTabsAndCopyImage'),
]
# Pages that should be run with GPU rasterization enabled.
......
......@@ -98,8 +98,10 @@
# Skip tab switching tests on Android webview and Fuchsia since they don't have tabs
[ android android-webview-instrumentation ] Pixel_Canvas2DTabSwitch [ Skip ]
[ android android-webview-instrumentation ] Pixel_WebGLReadPixelsTabSwitch [ Skip ]
[ android android-webview-instrumentation ] Pixel_WebGLPreservedAfterTabSwitch [ Skip ]
[ fuchsia ] Pixel_Canvas2DTabSwitch [ Skip ]
[ fuchsia ] Pixel_WebGLReadPixelsTabSwitch [ Skip ]
[ fuchsia ] Pixel_WebGLPreservedAfterTabSwitch [ Skip ]
# Fuchsia emulators don't support video
[ fuchsia fuchsia-board-qemu-x64 ] Pixel_Video* [ Skip ]
......
......@@ -1754,16 +1754,20 @@ bool WebGLRenderingContextBase::PaintRenderingResultsToCanvas(
return false;
bool must_clear_now = ClearIfComposited(kClearCallerOther) != kSkipped;
if (!must_paint_to_canvas_ && !must_clear_now)
return false;
must_paint_to_canvas_ = false;
if (Host()->ResourceProvider() &&
Host()->ResourceProvider()->Size() != GetDrawingBuffer()->Size()) {
Host()->DiscardResourceProvider();
}
// The host's ResourceProvider is purged to save memory when the tab
// is backgrounded.
if (!must_paint_to_canvas_ && !must_clear_now && Host()->ResourceProvider())
return false;
must_paint_to_canvas_ = false;
CanvasResourceProvider* resource_provider =
Host()->GetOrCreateCanvasResourceProvider(RasterModeHint::kPreferGPU);
if (!resource_provider)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment