diff options
author | Emilio Cobos Álvarez <emilio@crisal.io> | 2018-03-09 23:27:29 +0100 |
---|---|---|
committer | Emilio Cobos Álvarez <emilio@crisal.io> | 2018-03-09 23:27:29 +0100 |
commit | 21df4014db5ff11581fcdd328d2dd1f7226a4544 (patch) | |
tree | 41c071a3edd9320bb045ff055359d11a63a4439a | |
parent | 3fc5bf87d3fd605da7510a5a0240dac0157a9743 (diff) | |
download | servo-21df4014db5ff11581fcdd328d2dd1f7226a4544.tar.gz servo-21df4014db5ff11581fcdd328d2dd1f7226a4544.zip |
constellation: Make setting up the WebGL state fallible.
This fixes a regression caused by the glutin update.
We now are creating EGL contexts in Linux Wayland, instead of X context, so the
GLContextFactory assumption of one GL back-end per platform is broken.
This just works around it, for now, but in general I think not relying on
available WebGL state is a good thing, and we do that already for WebVR anyway.
-rw-r--r-- | components/canvas/gl_context.rs | 3 | ||||
-rw-r--r-- | components/constellation/constellation.rs | 14 | ||||
-rw-r--r-- | components/constellation/pipeline.rs | 6 | ||||
-rw-r--r-- | components/script/dom/webglrenderingcontext.rs | 6 | ||||
-rw-r--r-- | components/script/dom/window.rs | 8 | ||||
-rw-r--r-- | components/script/script_thread.rs | 6 | ||||
-rw-r--r-- | components/script_traits/lib.rs | 4 | ||||
-rw-r--r-- | components/servo/lib.rs | 34 |
8 files changed, 49 insertions, 32 deletions
diff --git a/components/canvas/gl_context.rs b/components/canvas/gl_context.rs index e0d686f622a..7720f8f678a 100644 --- a/components/canvas/gl_context.rs +++ b/components/canvas/gl_context.rs @@ -24,6 +24,9 @@ pub enum GLContextFactory { impl GLContextFactory { /// Creates a new GLContextFactory that uses the currently bound GL context to create shared contexts. pub fn current_native_handle(proxy: &CompositorProxy) -> Option<GLContextFactory> { + // FIXME(emilio): This assumes a single GL backend per platform which is + // not true on Linux, we probably need a third `Egl` variant or abstract + // it a bit more... NativeGLContext::current_handle().map(|handle| { if cfg!(target_os = "windows") { // Used to dispatch functions from the GLContext thread to the main thread's event loop. diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index f6a47ba14b1..cdc850495b1 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -325,7 +325,7 @@ pub struct Constellation<Message, LTF, STF> { phantom: PhantomData<(Message, LTF, STF)>, /// Entry point to create and get channels to a WebGLThread. - webgl_threads: WebGLThreads, + webgl_threads: Option<WebGLThreads>, /// A channel through which messages can be sent to the webvr thread. webvr_chan: Option<IpcSender<WebVRMsg>>, @@ -370,7 +370,7 @@ pub struct InitialConstellationState { pub webrender_api_sender: webrender_api::RenderApiSender, /// Entry point to create and get channels to a WebGLThread. - pub webgl_threads: WebGLThreads, + pub webgl_threads: Option<WebGLThreads>, /// A channel to the webgl thread. pub webvr_chan: Option<IpcSender<WebVRMsg>>, @@ -740,7 +740,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF> webrender_api_sender: self.webrender_api_sender.clone(), webrender_document: self.webrender_document, is_private, - webgl_chan: self.webgl_threads.pipeline(), + webgl_chan: self.webgl_threads.as_ref().map(|threads| threads.pipeline()), webvr_chan: self.webvr_chan.clone() }); @@ -1431,9 +1431,11 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF> } } - debug!("Exiting WebGL thread."); - if let Err(e) = self.webgl_threads.exit() { - warn!("Exit WebGL Thread failed ({})", e); + if let Some(webgl_threads) = self.webgl_threads.as_ref() { + debug!("Exiting WebGL thread."); + if let Err(e) = webgl_threads.exit() { + warn!("Exit WebGL Thread failed ({})", e); + } } if let Some(chan) = self.webvr_chan.as_ref() { diff --git a/components/constellation/pipeline.rs b/components/constellation/pipeline.rs index 4753f0ba3eb..99603cad805 100644 --- a/components/constellation/pipeline.rs +++ b/components/constellation/pipeline.rs @@ -170,8 +170,8 @@ pub struct InitialPipelineState { /// Whether this pipeline is considered private. pub is_private: bool, - /// A channel to the webgl thread. - pub webgl_chan: WebGLPipeline, + /// A channel to the WebGL thread. + pub webgl_chan: Option<WebGLPipeline>, /// A channel to the webvr thread. pub webvr_chan: Option<IpcSender<WebVRMsg>>, @@ -457,7 +457,7 @@ pub struct UnprivilegedPipelineContent { script_content_process_shutdown_port: IpcReceiver<()>, webrender_api_sender: webrender_api::RenderApiSender, webrender_document: webrender_api::DocumentId, - webgl_chan: WebGLPipeline, + webgl_chan: Option<WebGLPipeline>, webvr_chan: Option<IpcSender<WebVRMsg>>, } diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index fa1015582cf..0aabf2e319a 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -224,8 +224,12 @@ impl WebGLRenderingContext { return Err("WebGL context creation error forced by pref `webgl.testing.context_creation_error`".into()); } + let webgl_chan = match window.webgl_chan() { + Some(chan) => chan, + None => return Err("WebGL initialization failed early on".into()), + }; + let (sender, receiver) = webgl_channel().unwrap(); - let webgl_chan = window.webgl_chan(); webgl_chan.send(WebGLMsg::CreateContext(webgl_version, size, attrs, sender)) .unwrap(); let result = receiver.recv().unwrap(); diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 2cc1515b735..f6177e90fcf 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -257,9 +257,9 @@ pub struct Window { test_runner: MutNullableDom<TestRunner>, - /// A handle for communicating messages to the webvr thread, if available. + /// A handle for communicating messages to the WebGL thread, if available. #[ignore_malloc_size_of = "channels are hard"] - webgl_chan: WebGLChan, + webgl_chan: Option<WebGLChan>, /// A handle for communicating messages to the webvr thread, if available. #[ignore_malloc_size_of = "channels are hard"] @@ -402,7 +402,7 @@ impl Window { self.current_viewport.clone().get() } - pub fn webgl_chan(&self) -> WebGLChan { + pub fn webgl_chan(&self) -> Option<WebGLChan> { self.webgl_chan.clone() } @@ -1756,7 +1756,7 @@ impl Window { origin: MutableOrigin, navigation_start: u64, navigation_start_precise: u64, - webgl_chan: WebGLChan, + webgl_chan: Option<WebGLChan>, webvr_chan: Option<IpcSender<WebVRMsg>>, microtask_queue: Rc<MicrotaskQueue>, webrender_document: DocumentId, diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index f386d29487e..d949e9d0b8c 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -483,8 +483,8 @@ pub struct ScriptThread { /// The unit of related similar-origin browsing contexts' list of MutationObserver objects mutation_observers: DomRefCell<Vec<Dom<MutationObserver>>>, - /// A handle to the webgl thread - webgl_chan: WebGLPipeline, + /// A handle to the WebGL thread + webgl_chan: Option<WebGLPipeline>, /// A handle to the webvr thread, if available webvr_chan: Option<IpcSender<WebVRMsg>>, @@ -2130,7 +2130,7 @@ impl ScriptThread { origin, incomplete.navigation_start, incomplete.navigation_start_precise, - self.webgl_chan.channel(), + self.webgl_chan.as_ref().map(|chan| chan.channel()), self.webvr_chan.clone(), self.microtask_queue.clone(), self.webrender_document, diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs index eec50faf09b..46f5ed6c90c 100644 --- a/components/script_traits/lib.rs +++ b/components/script_traits/lib.rs @@ -539,8 +539,8 @@ pub struct InitialScriptState { pub pipeline_namespace_id: PipelineNamespaceId, /// A ping will be sent on this channel once the script thread shuts down. pub content_process_shutdown_chan: IpcSender<()>, - /// A channel to the webgl thread used in this pipeline. - pub webgl_chan: WebGLPipeline, + /// A channel to the WebGL thread used in this pipeline. + pub webgl_chan: Option<WebGLPipeline>, /// A channel to the webvr thread, if available. pub webvr_chan: Option<IpcSender<WebVRMsg>>, /// The Webrender document ID associated with this thread. diff --git a/components/servo/lib.rs b/components/servo/lib.rs index 8844625af19..45b6af50c89 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -566,23 +566,31 @@ fn create_constellation(user_agent: Cow<'static, str>, // GLContext factory used to create WebGL Contexts let gl_factory = if opts::get().should_use_osmesa() { - GLContextFactory::current_osmesa_handle().unwrap() + GLContextFactory::current_osmesa_handle() } else { - GLContextFactory::current_native_handle(&compositor_proxy).unwrap() + GLContextFactory::current_native_handle(&compositor_proxy) }; // Initialize WebGL Thread entry point. - let (webgl_threads, image_handler, output_handler) = WebGLThreads::new(gl_factory, - window_gl, - webrender_api_sender.clone(), - webvr_compositor.map(|c| c as Box<_>)); - // Set webrender external image handler for WebGL textures - webrender.set_external_image_handler(image_handler); - - // Set DOM to texture handler, if enabled. - if let Some(output_handler) = output_handler { - webrender.set_output_image_handler(output_handler); - } + let webgl_threads = gl_factory.map(|factory| { + let (webgl_threads, image_handler, output_handler) = + WebGLThreads::new( + factory, + window_gl, + webrender_api_sender.clone(), + webvr_compositor.map(|c| c as Box<_>), + ); + + // Set webrender external image handler for WebGL textures + webrender.set_external_image_handler(image_handler); + + // Set DOM to texture handler, if enabled. + if let Some(output_handler) = output_handler { + webrender.set_output_image_handler(output_handler); + } + + webgl_threads + }); let initial_state = InitialConstellationState { compositor_proxy, |