mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Use surfman for managing GL surfaces
Co-authored-by: Alan Jeffrey <ajeffrey@mozilla.com> Co-authored-by: Zakor Gyula <gyula.zakor@h-lab.eu> Co-authored-by: Josh Matthews <josh@joshmatthews.net>
This commit is contained in:
parent
48d918dcde
commit
a358bca766
52 changed files with 1929 additions and 2195 deletions
|
@ -64,8 +64,8 @@ fn webdriver(_port: u16, _constellation: Sender<ConstellationMsg>) {}
|
|||
|
||||
use bluetooth::BluetoothThreadFactory;
|
||||
use bluetooth_traits::BluetoothRequest;
|
||||
use canvas::gl_context::{CloneableDispatcher, GLContextFactory};
|
||||
use canvas::webgl_thread::{ThreadMode, WebGLMainThread, WebGLThreads};
|
||||
use canvas::WebGLComm;
|
||||
use canvas_traits::webgl::WebGLThreads;
|
||||
use compositing::compositor_thread::{
|
||||
CompositorProxy, CompositorReceiver, InitialCompositorState, Msg,
|
||||
};
|
||||
|
@ -100,7 +100,6 @@ use media::{GLPlayerThreads, WindowGLContext};
|
|||
use msg::constellation_msg::{PipelineNamespace, PipelineNamespaceId};
|
||||
use net::resource_thread::new_resource_threads;
|
||||
use net_traits::IpcSend;
|
||||
use offscreen_gl_context::GLContextDispatcher;
|
||||
use profile::mem as profile_mem;
|
||||
use profile::time as profile_time;
|
||||
use profile_traits::mem;
|
||||
|
@ -114,8 +113,17 @@ use std::borrow::Cow;
|
|||
use std::cmp::max;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
use std::sync::{Arc, Mutex};
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
use surfman::platform::default::device::Device as HWDevice;
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
use surfman::platform::generic::osmesa::device::Device as SWDevice;
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
use surfman::platform::generic::universal::context::Context;
|
||||
use surfman::platform::generic::universal::device::Device;
|
||||
use webrender::{RendererKind, ShaderPrecacheFlags};
|
||||
use webrender_traits::{WebrenderExternalImageHandlers, WebrenderImageHandlerType};
|
||||
use webrender_traits::WebrenderImageHandlerType;
|
||||
use webrender_traits::{WebrenderExternalImageHandlers, WebrenderExternalImageRegistry};
|
||||
use webvr::{VRServiceManager, WebVRCompositorHandler, WebVRThread};
|
||||
use webvr_traits::WebVRMsg;
|
||||
|
||||
|
@ -260,7 +268,6 @@ pub struct Servo<Window: WindowMethods + 'static + ?Sized> {
|
|||
embedder_receiver: EmbedderReceiver,
|
||||
embedder_events: Vec<(Option<BrowserId>, EmbedderMsg)>,
|
||||
profiler_enabled: bool,
|
||||
webgl_thread_data: Option<Rc<WebGLMainThread>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -328,7 +335,7 @@ where
|
|||
}
|
||||
|
||||
// Make sure the gl context is made current.
|
||||
window.prepare_for_composite();
|
||||
window.make_gl_context_current();
|
||||
|
||||
// Reserving a namespace to create TopLevelBrowserContextId.
|
||||
PipelineNamespace::install(PipelineNamespaceId(0));
|
||||
|
@ -451,58 +458,18 @@ where
|
|||
(None, None, None)
|
||||
};
|
||||
|
||||
// GLContext factory used to create WebGL Contexts
|
||||
let gl_factory = if opts.should_use_osmesa() {
|
||||
GLContextFactory::current_osmesa_handle()
|
||||
} else {
|
||||
let dispatcher =
|
||||
Box::new(MainThreadDispatcher::new(compositor_proxy.clone())) as Box<_>;
|
||||
let gl_type = match window.gl().get_type() {
|
||||
gl::GlType::Gl => sparkle::gl::GlType::Gl,
|
||||
gl::GlType::Gles => sparkle::gl::GlType::Gles,
|
||||
};
|
||||
GLContextFactory::current_native_handle(dispatcher, gl_type)
|
||||
};
|
||||
|
||||
let (external_image_handlers, external_images) = WebrenderExternalImageHandlers::new();
|
||||
let mut external_image_handlers = Box::new(external_image_handlers);
|
||||
|
||||
let run_webgl_on_main_thread =
|
||||
cfg!(windows) || std::env::var("SERVO_WEBGL_MAIN_THREAD").is_ok();
|
||||
|
||||
// Initialize WebGL Thread entry point.
|
||||
let webgl_result = gl_factory.map(|factory| {
|
||||
let (webgl_threads, thread_data, webxr_handler, image_handler, output_handler) =
|
||||
WebGLThreads::new(
|
||||
factory,
|
||||
window.gl(),
|
||||
webrender_api_sender.clone(),
|
||||
webvr_compositor.map(|c| c as Box<_>),
|
||||
external_images.clone(),
|
||||
if run_webgl_on_main_thread {
|
||||
ThreadMode::MainThread(embedder.create_event_loop_waker())
|
||||
} else {
|
||||
ThreadMode::OffThread
|
||||
},
|
||||
);
|
||||
|
||||
// Set webrender external image handler for WebGL textures
|
||||
external_image_handlers.set_handler(image_handler, WebrenderImageHandlerType::WebGL);
|
||||
|
||||
// Set webxr external image handler for WebGL textures
|
||||
webxr_main_thread.set_webgl(webxr_handler);
|
||||
|
||||
// Set DOM to texture handler, if enabled.
|
||||
if let Some(output_handler) = output_handler {
|
||||
webrender.set_output_image_handler(output_handler);
|
||||
}
|
||||
|
||||
(webgl_threads, thread_data)
|
||||
});
|
||||
let (webgl_threads, webgl_thread_data) = match webgl_result {
|
||||
Some((a, b)) => (Some(a), b),
|
||||
None => (None, None),
|
||||
};
|
||||
let webgl_threads = create_webgl_threads(
|
||||
&*window,
|
||||
&mut webrender,
|
||||
webrender_api_sender.clone(),
|
||||
webvr_compositor,
|
||||
&mut webxr_main_thread,
|
||||
&mut external_image_handlers,
|
||||
external_images.clone(),
|
||||
);
|
||||
|
||||
let glplayer_threads = match window.get_gl_context() {
|
||||
GlContext::Unknown => None,
|
||||
|
@ -523,16 +490,7 @@ where
|
|||
|
||||
webrender.set_external_image_handler(external_image_handlers);
|
||||
|
||||
// When webgl execution occurs on the main thread, and the script thread
|
||||
// lives in the same process, then the script thread needs the ability to
|
||||
// wake up the main thread's event loop when webgl commands need processing.
|
||||
// When there are multiple processes, this is handled automatically by
|
||||
// the IPC receiving handler instead.
|
||||
let event_loop_waker = if run_webgl_on_main_thread && !opts.multiprocess {
|
||||
Some(embedder.create_event_loop_waker())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let event_loop_waker = None;
|
||||
|
||||
// Create the constellation, which maintains the engine
|
||||
// pipelines, including the script and layout threads, as well
|
||||
|
@ -550,7 +508,7 @@ where
|
|||
webrender_api_sender,
|
||||
webxr_main_thread.registry(),
|
||||
player_context,
|
||||
webgl_threads,
|
||||
Some(webgl_threads),
|
||||
webvr_chan,
|
||||
webvr_constellation_sender,
|
||||
glplayer_threads,
|
||||
|
@ -596,7 +554,6 @@ where
|
|||
embedder_receiver: embedder_receiver,
|
||||
embedder_events: Vec::new(),
|
||||
profiler_enabled: false,
|
||||
webgl_thread_data,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -788,10 +745,6 @@ where
|
|||
}
|
||||
|
||||
pub fn handle_events(&mut self, events: Vec<WindowEvent>) {
|
||||
if let Some(ref mut webgl_thread) = self.webgl_thread_data {
|
||||
webgl_thread.process();
|
||||
}
|
||||
|
||||
if self.compositor.receive_messages() {
|
||||
self.receive_messages();
|
||||
}
|
||||
|
@ -1052,28 +1005,68 @@ fn create_sandbox() {
|
|||
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,
|
||||
}
|
||||
// Initializes the WebGL thread.
|
||||
fn create_webgl_threads<W>(
|
||||
window: &W,
|
||||
webrender: &mut webrender::Renderer,
|
||||
webrender_api_sender: webrender_api::RenderApiSender,
|
||||
webvr_compositor: Option<Box<WebVRCompositorHandler>>,
|
||||
webxr_main_thread: &mut webxr_api::MainThreadRegistry,
|
||||
external_image_handlers: &mut WebrenderExternalImageHandlers,
|
||||
external_images: Arc<Mutex<WebrenderExternalImageRegistry>>,
|
||||
) -> WebGLThreads
|
||||
where
|
||||
W: WindowMethods + 'static + ?Sized,
|
||||
{
|
||||
// Create a `surfman` device and context.
|
||||
window.make_gl_context_current();
|
||||
|
||||
impl MainThreadDispatcher {
|
||||
fn new(proxy: CompositorProxy) -> Self {
|
||||
Self {
|
||||
compositor_proxy: proxy,
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
let (device, context) = unsafe {
|
||||
if opts::get().headless {
|
||||
let (device, context) = SWDevice::from_current_context()
|
||||
.expect("Failed to create software graphics context!");
|
||||
(Device::Software(device), Context::Software(context))
|
||||
} else {
|
||||
let (device, context) = HWDevice::from_current_context()
|
||||
.expect("Failed to create hardware graphics context!");
|
||||
(Device::Hardware(device), Context::Hardware(context))
|
||||
}
|
||||
};
|
||||
#[cfg(target_os = "windows")]
|
||||
let (device, context) =
|
||||
unsafe { Device::from_current_context().expect("Failed to create graphics context!") };
|
||||
|
||||
let gl_type = match window.gl().get_type() {
|
||||
gleam::gl::GlType::Gl => sparkle::gl::GlType::Gl,
|
||||
gleam::gl::GlType::Gles => sparkle::gl::GlType::Gles,
|
||||
};
|
||||
|
||||
let WebGLComm {
|
||||
webgl_threads,
|
||||
webxr_swap_chains,
|
||||
image_handler,
|
||||
output_handler,
|
||||
} = WebGLComm::new(
|
||||
device,
|
||||
context,
|
||||
window.gl(),
|
||||
webrender_api_sender,
|
||||
webvr_compositor.map(|compositor| compositor as Box<_>),
|
||||
external_images,
|
||||
gl_type,
|
||||
);
|
||||
|
||||
// Set webrender external image handler for WebGL textures
|
||||
external_image_handlers.set_handler(image_handler, WebrenderImageHandlerType::WebGL);
|
||||
|
||||
// Set webxr external image handler for WebGL textures
|
||||
webxr_main_thread.set_swap_chains(webxr_swap_chains);
|
||||
|
||||
// Set DOM to texture handler, if enabled.
|
||||
if let Some(output_handler) = output_handler {
|
||||
webrender.set_output_image_handler(output_handler);
|
||||
}
|
||||
}
|
||||
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<_>
|
||||
}
|
||||
|
||||
webgl_threads
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue