Auto merge of #23758 - jdm:compositing-canvas-break, r=gterzian

Remove canvas->compositing dependency

There's one tiny place in the canvas crate that depends on the compositing crate, and it's really quite backwards. If we use trait objects instead it becomes much cleaner to reason about.

---
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] These changes do not require tests because no tests for windows-only webgl code.

<!-- 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/23758)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2019-07-12 10:26:55 -04:00 committed by GitHub
commit 812bf8d816
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 52 additions and 42 deletions

2
Cargo.lock generated
View file

@ -394,7 +394,6 @@ dependencies = [
"azure 0.36.0 (git+https://github.com/servo/rust-azure)", "azure 0.36.0 (git+https://github.com/servo/rust-azure)",
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"canvas_traits 0.0.1", "canvas_traits 0.0.1",
"compositing 0.0.1",
"cssparser 0.25.5 (registry+https://github.com/rust-lang/crates.io-index)", "cssparser 0.25.5 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.19.8 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.19.8 (registry+https://github.com/rust-lang/crates.io-index)",
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2542,6 +2541,7 @@ dependencies = [
"msg 0.0.1", "msg 0.0.1",
"net 0.0.1", "net 0.0.1",
"net_traits 0.0.1", "net_traits 0.0.1",
"offscreen_gl_context 0.22.3 (registry+https://github.com/rust-lang/crates.io-index)",
"profile 0.0.1", "profile 0.0.1",
"profile_traits 0.0.1", "profile_traits 0.0.1",
"script 0.0.1", "script 0.0.1",

View file

@ -21,7 +21,6 @@ no_wgl = ["offscreen_gl_context/no_wgl"]
azure = {git = "https://github.com/servo/rust-azure", optional = true} azure = {git = "https://github.com/servo/rust-azure", optional = true}
byteorder = "1" byteorder = "1"
canvas_traits = {path = "../canvas_traits"} canvas_traits = {path = "../canvas_traits"}
compositing = {path = "../compositing"}
cssparser = "0.25" cssparser = "0.25"
euclid = "0.19" euclid = "0.19"
fnv = "1.0" fnv = "1.0"

View file

@ -6,7 +6,6 @@ use super::webgl_thread::{GLState, WebGLImpl};
use canvas_traits::webgl::{ use canvas_traits::webgl::{
GLContextAttributes, GLLimits, WebGLCommand, WebGLCommandBacktrace, WebGLVersion, GLContextAttributes, GLLimits, WebGLCommand, WebGLCommandBacktrace, WebGLVersion,
}; };
use compositing::compositor_thread::{self, CompositorProxy};
use euclid::Size2D; use euclid::Size2D;
use gleam::gl; use gleam::gl;
use offscreen_gl_context::{ use offscreen_gl_context::{
@ -16,31 +15,38 @@ use offscreen_gl_context::{
use offscreen_gl_context::{GLLimits as RawGLLimits, GLVersion}; use offscreen_gl_context::{GLLimits as RawGLLimits, GLVersion};
use offscreen_gl_context::{NativeGLContext, NativeGLContextHandle, NativeGLContextMethods}; use offscreen_gl_context::{NativeGLContext, NativeGLContextHandle, NativeGLContextMethods};
use offscreen_gl_context::{OSMesaContext, OSMesaContextHandle}; use offscreen_gl_context::{OSMesaContext, OSMesaContextHandle};
use std::sync::{Arc, Mutex};
pub trait CloneableDispatcher: GLContextDispatcher {
fn clone(&self) -> Box<dyn GLContextDispatcher>;
}
/// The GLContextFactory is used to create shared GL contexts with the main thread GL context. /// The GLContextFactory is used to create shared GL contexts with the main thread GL context.
/// Currently, shared textures are used to render WebGL textures into the WR compositor. /// Currently, shared textures are used to render WebGL textures into the WR compositor.
/// In order to create a shared context, the GLContextFactory stores the handle of the main GL context. /// In order to create a shared context, the GLContextFactory stores the handle of the main GL context.
pub enum GLContextFactory { pub enum GLContextFactory {
Native(NativeGLContextHandle, Option<MainThreadDispatcher>), Native(
NativeGLContextHandle,
Option<Box<dyn CloneableDispatcher + Send>>,
),
OSMesa(OSMesaContextHandle), OSMesa(OSMesaContextHandle),
} }
impl GLContextFactory { impl GLContextFactory {
/// Creates a new GLContextFactory that uses the currently bound GL context to create shared contexts. /// Creates a new GLContextFactory that uses the currently bound GL context to create shared contexts.
pub fn current_native_handle(proxy: &CompositorProxy) -> Option<GLContextFactory> { pub fn current_native_handle(
dispatcher: Box<dyn CloneableDispatcher + Send>,
) -> Option<GLContextFactory> {
let dispatcher = if cfg!(target_os = "windows") {
// Used to dispatch functions from the GLContext thread to the main thread's
// event loop. Required to allow WGL GLContext sharing in Windows.
Some(dispatcher)
} else {
None
};
// FIXME(emilio): This assumes a single GL backend per platform which is // 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 // not true on Linux, we probably need a third `Egl` variant or abstract
// it a bit more... // it a bit more...
NativeGLContext::current_handle().map(|handle| { NativeGLContext::current_handle().map(|handle| GLContextFactory::Native(handle, dispatcher))
if cfg!(target_os = "windows") {
// Used to dispatch functions from the GLContext thread to the main thread's event loop.
// Required to allow WGL GLContext sharing in Windows.
GLContextFactory::Native(handle, Some(MainThreadDispatcher::new(proxy.clone())))
} else {
GLContextFactory::Native(handle, None)
}
})
} }
/// Creates a new GLContextFactory that uses the currently bound OSMesa context to create shared contexts. /// Creates a new GLContextFactory that uses the currently bound OSMesa context to create shared contexts.
@ -58,7 +64,6 @@ impl GLContextFactory {
let attributes = map_attrs(attributes); let attributes = map_attrs(attributes);
Ok(match *self { Ok(match *self {
GLContextFactory::Native(ref handle, ref dispatcher) => { GLContextFactory::Native(ref handle, ref dispatcher) => {
let dispatcher = dispatcher.as_ref().map(|d| Box::new(d.clone()) as Box<_>);
GLContextWrapper::Native(GLContext::new_shared_with_dispatcher( GLContextWrapper::Native(GLContext::new_shared_with_dispatcher(
// FIXME(nox): Why are those i32 values? // FIXME(nox): Why are those i32 values?
size.to_i32(), size.to_i32(),
@ -67,7 +72,7 @@ impl GLContextFactory {
gl::GlType::default(), gl::GlType::default(),
Self::gl_version(webgl_version), Self::gl_version(webgl_version),
Some(handle), Some(handle),
dispatcher, dispatcher.as_ref().map(|d| (**d).clone()),
)?) )?)
}, },
GLContextFactory::OSMesa(ref handle) => { GLContextFactory::OSMesa(ref handle) => {
@ -215,29 +220,6 @@ impl GLContextWrapper {
} }
} }
/// Implements GLContextDispatcher to dispatch functions from GLContext threads to the main thread's event loop.
/// It's used in Windows to allow WGL GLContext sharing.
#[derive(Clone)]
pub struct MainThreadDispatcher {
compositor_proxy: Arc<Mutex<CompositorProxy>>,
}
impl MainThreadDispatcher {
fn new(proxy: CompositorProxy) -> Self {
Self {
compositor_proxy: Arc::new(Mutex::new(proxy)),
}
}
}
impl GLContextDispatcher for MainThreadDispatcher {
fn dispatch(&self, f: Box<dyn Fn() + Send>) {
self.compositor_proxy
.lock()
.unwrap()
.send(compositor_thread::Msg::Dispatch(f));
}
}
fn map_limits(limits: RawGLLimits) -> GLLimits { fn map_limits(limits: RawGLLimits) -> GLLimits {
GLLimits { GLLimits {
max_vertex_attribs: limits.max_vertex_attribs, max_vertex_attribs: limits.max_vertex_attribs,

View file

@ -60,6 +60,7 @@ layout_thread_2020 = {path = "../layout_thread_2020", optional = true}
log = "0.4" log = "0.4"
media = {path = "../media"} media = {path = "../media"}
msg = {path = "../msg"} msg = {path = "../msg"}
offscreen_gl_context = "0.22"
net = {path = "../net"} net = {path = "../net"}
net_traits = {path = "../net_traits"} net_traits = {path = "../net_traits"}
profile = {path = "../profile"} profile = {path = "../profile"}

View file

@ -64,7 +64,7 @@ fn webdriver(_port: u16, _constellation: Sender<ConstellationMsg>) {}
use bluetooth::BluetoothThreadFactory; use bluetooth::BluetoothThreadFactory;
use bluetooth_traits::BluetoothRequest; use bluetooth_traits::BluetoothRequest;
use canvas::gl_context::GLContextFactory; use canvas::gl_context::{CloneableDispatcher, GLContextFactory};
use canvas::webgl_thread::WebGLThreads; use canvas::webgl_thread::WebGLThreads;
use compositing::compositor_thread::{ use compositing::compositor_thread::{
CompositorProxy, CompositorReceiver, InitialCompositorState, Msg, CompositorProxy, CompositorReceiver, InitialCompositorState, Msg,
@ -100,6 +100,7 @@ use media::{GLPlayerThreads, WindowGLContext};
use msg::constellation_msg::{PipelineNamespace, PipelineNamespaceId}; use msg::constellation_msg::{PipelineNamespace, PipelineNamespaceId};
use net::resource_thread::new_resource_threads; use net::resource_thread::new_resource_threads;
use net_traits::IpcSend; use net_traits::IpcSend;
use offscreen_gl_context::GLContextDispatcher;
use profile::mem as profile_mem; use profile::mem as profile_mem;
use profile::time as profile_time; use profile::time as profile_time;
use profile_traits::mem; use profile_traits::mem;
@ -745,7 +746,8 @@ fn create_constellation(
let gl_factory = if opts.should_use_osmesa() { let gl_factory = if opts.should_use_osmesa() {
GLContextFactory::current_osmesa_handle() GLContextFactory::current_osmesa_handle()
} else { } else {
GLContextFactory::current_native_handle(&compositor_proxy) let dispatcher = Box::new(MainThreadDispatcher::new(compositor_proxy.clone())) as Box<_>;
GLContextFactory::current_native_handle(dispatcher)
}; };
let (external_image_handlers, external_images) = WebrenderExternalImageHandlers::new(); let (external_image_handlers, external_images) = WebrenderExternalImageHandlers::new();
@ -937,3 +939,29 @@ fn create_sandbox() {
fn create_sandbox() { fn create_sandbox() {
panic!("Sandboxing is not supported on Windows, iOS, ARM targets and android."); panic!("Sandboxing is not supported on Windows, iOS, ARM targets and android.");
} }
/// Implements GLContextDispatcher to dispatch functions from GLContext threads to the main thread's event loop.
/// It's used in Windows to allow WGL GLContext sharing.
pub struct MainThreadDispatcher {
compositor_proxy: CompositorProxy,
}
impl MainThreadDispatcher {
fn new(proxy: CompositorProxy) -> Self {
Self {
compositor_proxy: proxy,
}
}
}
impl GLContextDispatcher for MainThreadDispatcher {
fn dispatch(&self, f: Box<dyn Fn() + Send>) {
self.compositor_proxy.send(Msg::Dispatch(f));
}
}
impl CloneableDispatcher for MainThreadDispatcher {
fn clone(&self) -> Box<dyn GLContextDispatcher> {
Box::new(MainThreadDispatcher {
compositor_proxy: self.compositor_proxy.clone(),
}) as Box<_>
}
}