Auto merge of #23000 - jdm:invisible-webgl, r=nox

Make webgl behave better with session history

This prevents the compositor from animating pages that are not actually visible, so pages using webgl do not needlessly impact the performance of the rest of the browser. Additionally, this fixes a problem that was alluded to in [this code](b5228c098b/src/draw_buffer.rs (L282-L285)), causing Servo to delete arbitrary resources when a GC occurred in content that used three.js.

- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] These changes fix #22987 and fix #22977 and fix #20934 and fix #20953 and fix #20930 and fix #20950 and fix #20924
- [x] There are tests for these changes

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/23000)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2019-03-08 10:46:52 -05:00 committed by GitHub
commit 34a5a824b8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 145 additions and 0 deletions

View file

@ -380,6 +380,10 @@ impl<VR: WebVRRenderHandler + 'static> WebGLThread<VR> {
self.webrender_api.update_resources(txn.resource_updates) self.webrender_api.update_resources(txn.resource_updates)
} }
// We need to make the context current so its resources can be disposed of.
let _ =
Self::make_current_if_needed(context_id, &self.contexts, &mut self.bound_context_id);
// Release GL context. // Release GL context.
self.contexts.remove(&context_id); self.contexts.remove(&context_id);

View file

@ -2694,6 +2694,13 @@ where
}, },
}; };
if let Some(old_pipeline) = self.pipelines.get(&old_pipeline_id) {
old_pipeline.notify_visibility(false);
}
if let Some(new_pipeline) = self.pipelines.get(&new_pipeline_id) {
new_pipeline.notify_visibility(true);
}
self.update_activity(old_pipeline_id); self.update_activity(old_pipeline_id);
self.update_activity(new_pipeline_id); self.update_activity(new_pipeline_id);
@ -3413,6 +3420,10 @@ where
self.notify_history_changed(change.top_level_browsing_context_id); self.notify_history_changed(change.top_level_browsing_context_id);
}, },
Some(old_pipeline_id) => { Some(old_pipeline_id) => {
if let Some(pipeline) = self.pipelines.get(&old_pipeline_id) {
pipeline.notify_visibility(false);
}
// https://html.spec.whatwg.org/multipage/#unload-a-document // https://html.spec.whatwg.org/multipage/#unload-a-document
self.unload_document(old_pipeline_id); self.unload_document(old_pipeline_id);
// Deactivate the old pipeline, and activate the new one. // Deactivate the old pipeline, and activate the new one.

View file

@ -10614,6 +10614,16 @@
{} {}
] ]
], ],
"mozilla/webgl/clearcolor_blue.html": [
[
{}
]
],
"mozilla/webgl/clearcolor_green.html": [
[
{}
]
],
"mozilla/webgl/clearcolor_ref.html": [ "mozilla/webgl/clearcolor_ref.html": [
[ [
{} {}
@ -20120,6 +20130,14 @@
"4760f382f0374985a334a5f6d0e0fe055670c61d", "4760f382f0374985a334a5f6d0e0fe055670c61d",
"reftest" "reftest"
], ],
"mozilla/webgl/clearcolor_blue.html": [
"d534babb2a664b7cb861f1cc253020e319f281e9",
"support"
],
"mozilla/webgl/clearcolor_green.html": [
"db11b31ab9839777d9d74cf7f2c46de00349c76e",
"support"
],
"mozilla/webgl/clearcolor_ref.html": [ "mozilla/webgl/clearcolor_ref.html": [
"49cce2cc9009057742cb17e3fd452a986bd6c177", "49cce2cc9009057742cb17e3fd452a986bd6c177",
"support" "support"
@ -20144,6 +20162,10 @@
"691535db4766536d66769408212cb13f3f64bef6", "691535db4766536d66769408212cb13f3f64bef6",
"testharness" "testharness"
], ],
"mozilla/webgl/history.html": [
"d470c229fbcca5a47d3370e8e58bae34882be491",
"testharness"
],
"mozilla/webgl/img/rust-logo-256x256.png": [ "mozilla/webgl/img/rust-logo-256x256.png": [
"63506dd85efce44f8433942a6f4e54d718a97046", "63506dd85efce44f8433942a6f4e54d718a97046",
"support" "support"

View file

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>WebGL ClearColor Test</title>
</head>
<style>
html, body {
margin: 0;
}
</style>
<body>
<canvas id="canvas" width="640" height="480"></canvas>
<!-- Dummy canvas that is only used to create a GL context that will be garbage collected -->
<canvas id="canvas2" width="640" height="480"></canvas>
<script type="text/javascript">
var gl = document.getElementById("canvas").getContext("webgl");
var gl2 = document.getElementById("canvas2").getContext("webgl");
gl2 = null;
document.getElementById('canvas2').remove();
function draw() {
gl.clearColor(0.0, 0.0, 1.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
}
draw();
</script>
</body>
</html>

View file

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>WebGL ClearColor Test</title>
</head>
<style>
html, body {
margin: 0;
}
</style>
<body>
<canvas id="canvas" width="640" height="480"></canvas>
<!-- Dummy canvas that is only used to create a GL context that will be garbage collected -->
<canvas id="canvas2" width="640" height="480"></canvas>
<script type="text/javascript">
var gl = document.getElementById("canvas").getContext("webgl");
var gl2 = document.getElementById("canvas2").getContext("webgl");
gl2 = null;
document.getElementById('canvas2').remove();
function draw() {
gl.clearColor(0.0, 1.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
}
draw();
</script>
</body>
</html>

View file

@ -0,0 +1,42 @@
<!doctype html>
<meta charset="utf-8">
<title>Traversing history with webgl content does not panic</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<iframe></iframe>
<script>
/*
Load two pages that each create two GL contexts and draw in one of them.
Traverse history and attempt to draw again; this has historically caused crashes.
*/
var first = "clearcolor_green.html";
var second = "clearcolor_blue.html";
var iframe = document.querySelector('iframe');
iframe.src = first;
var t = async_test();
onload = t.step_func(function() {
iframe.src = second;
iframe.onload = t.step_func(function() {
assert_true(iframe.contentWindow.location.href.endsWith(second));
iframe.contentWindow.history.back();
t.step_timeout(function() {
assert_true(iframe.contentWindow.location.href.endsWith(first));
// Try to use the previously-used GL context.
iframe.contentWindow.draw();
iframe.contentWindow.history.forward();
t.step_timeout(function() {
assert_true(iframe.contentWindow.location.href.endsWith(second));
// Try to use the previously-used GL context.
iframe.contentWindow.draw();
t.done();
}, 1000);
}, 1000);
});
});
</script>