Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: switch to glutin #163

Merged
merged 13 commits into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 59 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 3 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,13 @@ env_logger = "0.10"
euclid = "0.22"
getopts = "0.2.17"
gleam = "0.15"
glutin = "0.32.0"
glutin-winit = "0.5.0"
ipc-channel = "0.18"
keyboard-types = "0.7"
log = "0.4"
raw-window-handle = { version = "0.6", features = ["std"] }
sparkle = "0.1.26"
surfman = { version = "0.9", features = ["chains", "sm-raw-window-handle-06"] }
thiserror = "1.0"
winit = { version = "0.30", features = ["rwh_06"] }
# Servo repo crates
Expand Down Expand Up @@ -99,10 +100,6 @@ cargo-packager-resource-resolver = { version = "0.1.1", features = [
], optional = true }
url = "2.5.2"

[target.'cfg(target_os = "windows")'.dependencies]
surfman = { version = "0.9", features = ["sm-angle-default"] }
mozangle = { version = "0.5.1", features = ["egl", "build_dlls"] }

[target.'cfg(any(target_os = "ios", target_os = "macos"))'.dependencies]
objc2 = "0.5"
objc2-app-kit = {version = "0.2", features = ["NSView", "NSResponder", "NSWindow"]}
Expand All @@ -117,4 +114,4 @@ lto = true

# Tell clippy to allow e.g. #[cfg(macos)]
[lints.clippy]
mismatched_target_os = "allow"
mismatched_target_os = "allow"
122 changes: 35 additions & 87 deletions src/compositor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ use script_traits::{
};
use servo_geometry::DeviceIndependentPixel;
use style_traits::{CSSPixel, DevicePixel, PinchZoomFactor};
use surfman::Surface;
use webrender::{RenderApi, Transaction};
use webrender_api::units::{
DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePoint, LayoutPoint, LayoutRect, LayoutSize,
Expand All @@ -39,11 +38,11 @@ use webrender_api::{
use webrender_traits::display_list::{HitTestInfo, ScrollTree};
use webrender_traits::{
CanvasToCompositorMsg, CompositorHitTestResult, FontToCompositorMsg, ImageUpdate,
NetToCompositorMsg, RenderingContext, ScriptToCompositorMsg, SerializedImageUpdate,
UntrustedNodeAddress,
NetToCompositorMsg, ScriptToCompositorMsg, SerializedImageUpdate, UntrustedNodeAddress,
};
use winit::window::WindowId;

use crate::rendering::RenderingContext;
use crate::touch::{TouchAction, TouchHandler};
use crate::window::Window;

Expand Down Expand Up @@ -104,9 +103,6 @@ const MIN_ZOOM: f32 = 0.1;
/// The compositor will communicate with Servo using messages from the Constellation,
/// then composite the WebRender frames and present the surface to the window.
pub struct IOCompositor {
/// All surfaces that Compositor currently owns.
pub surfaces: HashMap<WindowId, Option<Surface>>,

/// The current window that Compositor is handling.
pub current_window: WindowId,

Expand Down Expand Up @@ -176,7 +172,7 @@ pub struct IOCompositor {
/// The webrender interface, if enabled.
pub webrender_api: RenderApi,

/// The surfman instance that webrender targets
/// The glutin instance that webrender targets
pub rendering_context: RenderingContext,

/// The GL bindings for webrender
Expand Down Expand Up @@ -348,10 +344,7 @@ impl IOCompositor {
exit_after_load: bool,
convert_mouse_to_touch: bool,
) -> Self {
let mut surfaces = HashMap::new();
surfaces.insert(current_window, None);
let compositor = IOCompositor {
surfaces,
current_window,
viewport,
port: state.receiver,
Expand Down Expand Up @@ -394,15 +387,7 @@ impl IOCompositor {
}

/// Consume compositor itself and deinit webrender.
pub fn deinit(mut self) {
if let Err(err) = self.rendering_context.make_gl_context_current() {
warn!("Failed to make GL context current: {:?}", err);
}
for surface in self.surfaces.values_mut() {
surface
.take()
.map(|s| self.rendering_context.destroy_surface(s));
}
pub fn deinit(self) {
self.webrender.deinit();
}

Expand Down Expand Up @@ -453,34 +438,6 @@ impl IOCompositor {
self.shutdown_state = ShutdownState::FinishedShuttingDown;
}

/// The underlying native surface can be lost during servo's lifetime.
/// On Android, for example, this happens when the app is sent to background.
/// We need to unbind the surface so that we don't try to use it again.
pub fn invalidate_native_surface(&mut self) {
debug!("Invalidating native surface in compositor");
if let Err(e) = self.rendering_context.unbind_native_surface_from_context() {
warn!("Unbinding native surface from context failed ({:?})", e);
}
}

/// On Android, this function will be called when the app moves to foreground
/// and the system creates a new native surface that needs to bound to the current
/// context.
#[allow(unsafe_code)]
#[allow(clippy::not_unsafe_ptr_arg_deref)] // It has an unsafe block inside
pub fn replace_native_surface(&mut self, native_widget: *mut c_void, coords: DeviceIntSize) {
debug!("Replacing native surface in compositor: {native_widget:?}");
let connection = self.rendering_context.connection();
let native_widget =
unsafe { connection.create_native_widget_from_ptr(native_widget, coords.to_untyped()) };
if let Err(e) = self
.rendering_context
.bind_native_surface_to_context(native_widget)
{
warn!("Binding native surface to context failed ({:?})", e);
}
}

fn handle_browser_message(
&mut self,
msg: CompositorMsg,
Expand Down Expand Up @@ -1282,23 +1239,16 @@ impl IOCompositor {
self.current_window,
window.id()
);
if let Some(Some(new_surface)) = self.surfaces.insert(window.id(), None) {
// Swap the surface
self.rendering_context.with_front_buffer(|_, old_surface| {
self.surfaces.insert(self.current_window, Some(old_surface));
new_surface
});
self.current_window = window.id();
self.scale_factor = Scale::new(window.scale_factor() as f32);
self.resize(window.size(), window);
}
self.current_window = window.id();
self.scale_factor = Scale::new(window.scale_factor() as f32);
self.resize(window.size(), window);
}
}

/// Resize the rendering context and all web views. Return true if the compositor should repaint and present
/// after this.
pub fn resize(&mut self, size: Size2D<i32, DevicePixel>, window: &mut Window) -> bool {
let need_resize = self.on_resize_window_event(size);
let need_resize = self.on_resize_window_event(size, window);

if let Some(panel) = &mut window.panel {
let rect = DeviceIntRect::from_size(size);
Expand All @@ -1319,12 +1269,14 @@ impl IOCompositor {

/// Handle the window resize event and return a boolean to tell embedder if it should further
/// handle the resize event.
pub fn on_resize_window_event(&mut self, new_viewport: DeviceIntSize) -> bool {
pub fn on_resize_window_event(&mut self, new_viewport: DeviceIntSize, window: &Window) -> bool {
if self.shutdown_state != ShutdownState::NotShuttingDown {
return false;
}

let _ = self.rendering_context.resize(new_viewport.to_untyped());
let _ = self
.rendering_context
.resize(&window.surface, new_viewport.to_untyped());
self.viewport = new_viewport;
let mut transaction = Transaction::new();
transaction.set_document_view(DeviceIntRect::from_size(self.viewport));
Expand Down Expand Up @@ -1959,8 +1911,8 @@ impl IOCompositor {
}

/// Composite to the given target if any, or the current target otherwise.
pub fn composite(&mut self) {
match self.composite_specific_target() {
pub fn composite(&mut self, window: &Window) {
match self.composite_specific_target(window) {
Ok(_) => {
if self.exit_after_load {
println!("Shutting down the Constellation after generating an output file or exit flag specified");
Expand All @@ -1974,8 +1926,11 @@ impl IOCompositor {
}

/// Composite to the given target if any, or the current target otherwise.
fn composite_specific_target(&mut self) -> Result<(), UnableToComposite> {
if let Err(err) = self.rendering_context.make_gl_context_current() {
fn composite_specific_target(&mut self, window: &Window) -> Result<(), UnableToComposite> {
if let Err(err) = self
.rendering_context
.make_gl_context_current(&window.surface)
{
warn!("Failed to make GL context current: {:?}", err);
}
self.assert_no_gl_error();
Expand All @@ -1999,17 +1954,6 @@ impl IOCompositor {
}
}

// Bind the webrender framebuffer
let framebuffer_object = self
.rendering_context
.context_surface_info()
.unwrap_or(None)
.map(|info| info.framebuffer_object)
.unwrap_or(0);
self.webrender_gl
.bind_framebuffer(gl::FRAMEBUFFER, framebuffer_object);
self.assert_gl_framebuffer_complete();

profile(
ProfilerCategory::Compositing,
None,
Expand Down Expand Up @@ -2071,7 +2015,7 @@ impl IOCompositor {
}
}

if let Err(err) = self.rendering_context.present() {
if let Err(err) = self.rendering_context.present(&window.surface) {
warn!("Failed to present surface: {:?}", err);
}
self.composition_request = CompositionRequest::NoCompositingNecessary;
Expand Down Expand Up @@ -2147,19 +2091,21 @@ impl IOCompositor {
self.zoom_action = false;
}

match self.composition_request {
CompositionRequest::NoCompositingNecessary => {}
CompositionRequest::CompositeNow(_) => self.composite(),
}
if let Some(window) = windows.get(&self.current_window) {
match self.composition_request {
CompositionRequest::NoCompositingNecessary => {}
CompositionRequest::CompositeNow(_) => self.composite(window),
}

// Run the WebXR main thread
self.webxr_main_thread.run_one_frame();
// Run the WebXR main thread
self.webxr_main_thread.run_one_frame();

// The WebXR thread may make a different context current
let _ = self.rendering_context.make_gl_context_current();
// The WebXR thread may make a different context current
let _ = self
.rendering_context
.make_gl_context_current(&window.surface);

if !self.pending_scroll_zoom_events.is_empty() {
if let Some(window) = windows.get(&self.current_window) {
if !self.pending_scroll_zoom_events.is_empty() {
self.process_pending_scroll_events(window)
}
}
Expand All @@ -2175,7 +2121,9 @@ impl IOCompositor {
let need_recomposite = matches!(msg, CompositorMsg::NewWebRenderFrameReady(_));
let keep_going = self.handle_browser_message(msg, windows);
if need_recomposite {
self.composite();
if let Some(window) = windows.get(&self.current_window) {
self.composite(window);
}
break;
}
if !keep_going {
Expand Down
3 changes: 3 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,7 @@ pub enum Error {
/// A general error that may occur while running the Winit event loop.
#[error(transparent)]
EventLoopError(#[from] winit::error::EventLoopError),
/// Glutin errors.
#[error(transparent)]
GlutinError(#[from] glutin::error::Error),
}
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ pub mod config;
pub mod errors;
/// Utilities to handle keyboard inputs and states.
pub mod keyboard;
/// Verso's rendering context.
pub mod rendering;
/// Utilities to handle touch inputs and states.
pub mod touch;
/// Main entry types and functions.
Expand Down
Loading