servo: Merge #20262 - constellation: Make setting up the WebGL state fallible (from emilio:webgl-fallible); r=jdm

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.

Source-Repo: https://github.com/servo/servo
Source-Revision: 95f9e14e67766b36a8b72e62925a34b1818be2c8

--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 0029f2ac9735f2645084e572e5f560f4348fa577
This commit is contained in:
Emilio Cobos Álvarez 2018-03-09 18:24:56 -05:00
Родитель 25d47480bb
Коммит bef3768170
8 изменённых файлов: 48 добавлений и 31 удалений

Просмотреть файл

@ -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.

Просмотреть файл

@ -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() {

Просмотреть файл

@ -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>>,
}

Просмотреть файл

@ -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();

Просмотреть файл

@ -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,

Просмотреть файл

@ -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,

Просмотреть файл

@ -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.

Просмотреть файл

@ -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);
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 DOM to texture handler, if enabled.
if let Some(output_handler) = output_handler {
webrender.set_output_image_handler(output_handler);
}
// 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,