diff --git a/components/webrender_surfman/lib.rs b/components/webrender_surfman/lib.rs index 9460417dc7e..8942cf42b0d 100644 --- a/components/webrender_surfman/lib.rs +++ b/components/webrender_surfman/lib.rs @@ -162,6 +162,23 @@ impl WebrenderSurfman { }) } + /// Invoke a closure with the surface associated with the current front buffer. + /// This can be used to create a surfman::SurfaceTexture to blit elsewhere. + pub fn with_front_buffer Surface>(&self, mut f: F) { + let ref mut device = self.0.device.borrow_mut(); + let ref mut context = self.0.context.borrow_mut(); + let surface = device + .unbind_surface_from_context(context) + .unwrap() + .unwrap(); + let surface = f(device, surface); + device.bind_surface_to_context(context, surface).unwrap(); + } + + pub fn device(&self) -> std::cell::Ref { + self.0.device.borrow() + } + pub fn connection(&self) -> Connection { let ref device = self.0.device.borrow(); device.connection() diff --git a/ports/libsimpleservo/api/src/lib.rs b/ports/libsimpleservo/api/src/lib.rs index 4c1523b6067..c87a63f4445 100644 --- a/ports/libsimpleservo/api/src/lib.rs +++ b/ports/libsimpleservo/api/src/lib.rs @@ -63,10 +63,18 @@ pub struct InitOptions { pub xr_discovery: Option, pub gl_context_pointer: Option<*const c_void>, pub native_display_pointer: Option<*const c_void>, - pub native_widget: *mut c_void, + pub surfman_integration: SurfmanIntegration, pub prefs: Option>, } +/// Controls how this embedding's rendering will integrate with the embedder. +pub enum SurfmanIntegration { + /// Render directly to a provided native widget (see surfman::NativeWidget). + Widget(*mut c_void), + /// Render to an offscreen surface. + Surface, +} + #[derive(Clone, Debug)] pub struct Coordinates { pub viewport: Rect, @@ -153,6 +161,7 @@ pub trait HostTrait { } pub struct ServoGlue { + webrender_surfman: WebrenderSurfman, servo: Servo, batch_mode: bool, callbacks: Rc, @@ -253,13 +262,21 @@ pub fn init( .create_adapter() .or(Err("Failed to create adapter"))?, }; - let native_widget = unsafe { - connection.create_native_widget_from_ptr( - init_opts.native_widget, - init_opts.coordinates.framebuffer.to_untyped(), - ) + let surface_type = match init_opts.surfman_integration { + SurfmanIntegration::Widget(native_widget) => { + let native_widget = unsafe { + connection.create_native_widget_from_ptr( + native_widget, + init_opts.coordinates.framebuffer.to_untyped(), + ) + }; + SurfaceType::Widget { native_widget } + }, + SurfmanIntegration::Surface => { + let size = init_opts.coordinates.framebuffer.to_untyped(); + SurfaceType::Generic { size } + }, }; - let surface_type = SurfaceType::Widget { native_widget }; let webrender_surfman = WebrenderSurfman::create(&connection, &adapter, surface_type) .or(Err("Failed to create surface manager"))?; @@ -269,7 +286,7 @@ pub fn init( density: init_opts.density, gl_context_pointer: init_opts.gl_context_pointer, native_display_pointer: init_opts.native_display_pointer, - webrender_surfman, + webrender_surfman: webrender_surfman.clone(), }); let embedder_callbacks = Box::new(ServoEmbedderCallbacks { @@ -282,6 +299,7 @@ pub fn init( SERVO.with(|s| { let mut servo_glue = ServoGlue { + webrender_surfman, servo, batch_mode: false, callbacks: window_callbacks, @@ -322,6 +340,12 @@ impl ServoGlue { self.servo.deinit(); } + /// Returns the webrender surface management integration interface. + /// This provides the embedder access to the current front buffer. + pub fn surfman(&self) -> WebrenderSurfman { + self.webrender_surfman.clone() + } + /// This is the Servo heartbeat. This needs to be called /// everytime wakeup is called or when embedder wants Servo /// to act on its pending events. diff --git a/ports/libsimpleservo/capi/src/lib.rs b/ports/libsimpleservo/capi/src/lib.rs index 0ea0e83e12f..4fa94965502 100644 --- a/ports/libsimpleservo/capi/src/lib.rs +++ b/ports/libsimpleservo/capi/src/lib.rs @@ -21,6 +21,7 @@ use simpleservo::{self, gl_glue, ServoGlue, SERVO}; use simpleservo::{ ContextMenuResult, Coordinates, DeviceIntRect, EventLoopWaker, HostTrait, InitOptions, InputMethodType, MediaSessionActionType, MediaSessionPlaybackState, MouseButton, PromptResult, + SurfmanIntegration, }; use std::ffi::{CStr, CString}; #[cfg(target_os = "windows")] @@ -463,7 +464,7 @@ unsafe fn init( xr_discovery: None, gl_context_pointer: gl_context, native_display_pointer: display, - native_widget: opts.native_widget, + surfman_integration: SurfmanIntegration::Widget(opts.native_widget), }; let wakeup = Box::new(WakeupCallback::new(wakeup));