Simplify RenderingContext trait methods (#35251)

There are a few methods are still difficult to implement without
the help of surfman. To simplify the trait methods, all methods that
return surfman types are removed. They are either handled by
embedders themselves or abstract to simpler types that servo
components need. The most noticeable changes are:

- Methods related to native surface are moved to servo_glue. The
  embedder should decide when to remove/replace the surface and it's
  outside of servo's scope.
- Methods required by servo media now return exact media types for it.

The other major change is sevevral difficult trait methods that are
reuiqred by WebGL and Servo media have default implementation. So they
can be optional for users to implement.

Signed-off-by: Wu Wayne <yuweiwu@pm.me>
This commit is contained in:
Ngo Iok Ui (Wu Yu Wei) 2025-02-05 21:02:11 +09:00 committed by GitHub
parent 175f28866d
commit 07aa4ce093
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 176 additions and 230 deletions

1
Cargo.lock generated
View file

@ -8609,6 +8609,7 @@ dependencies = [
"libc", "libc",
"log", "log",
"serde", "serde",
"servo-media",
"servo_geometry", "servo_geometry",
"surfman", "surfman",
"webrender_api", "webrender_api",

View file

@ -48,6 +48,10 @@ impl WebGLComm {
let webxr_init = crate::webxr::WebXRBridgeInit::new(sender.clone()); let webxr_init = crate::webxr::WebXRBridgeInit::new(sender.clone());
#[cfg(feature = "webxr")] #[cfg(feature = "webxr")]
let webxr_layer_grand_manager = webxr_init.layer_grand_manager(); let webxr_layer_grand_manager = webxr_init.layer_grand_manager();
let connection = surfman::Connection::new().expect("Failed to create connection");
let adapter = connection
.create_adapter()
.expect("Failed to create adapter");
// This implementation creates a single `WebGLThread` for all the pipelines. // This implementation creates a single `WebGLThread` for all the pipelines.
let init = WebGLThreadInit { let init = WebGLThreadInit {
@ -57,8 +61,8 @@ impl WebGLComm {
sender: sender.clone(), sender: sender.clone(),
receiver, receiver,
webrender_swap_chains: webrender_swap_chains.clone(), webrender_swap_chains: webrender_swap_chains.clone(),
connection: rendering_context.connection(), connection,
adapter: rendering_context.adapter(), adapter,
api_type, api_type,
#[cfg(feature = "webxr")] #[cfg(feature = "webxr")]
webxr_init, webxr_init,
@ -100,23 +104,30 @@ impl WebGLExternalImages {
debug!("... locking chain {:?}", id); debug!("... locking chain {:?}", id);
let front_buffer = self.swap_chains.get(id)?.take_surface()?; let front_buffer = self.swap_chains.get(id)?.take_surface()?;
let (surface_texture, gl_texture, size) = if let Some((surface_texture, gl_texture, size)) =
self.rendering_context.create_texture(front_buffer); self.rendering_context.create_texture(front_buffer)
{
self.locked_front_buffers.insert(id, surface_texture); self.locked_front_buffers.insert(id, surface_texture);
Some((gl_texture, size)) Some((gl_texture, size))
} else {
None
}
} }
fn unlock_swap_chain(&mut self, id: WebGLContextId) -> Option<()> { fn unlock_swap_chain(&mut self, id: WebGLContextId) -> Option<()> {
let locked_front_buffer = self.locked_front_buffers.remove(&id)?;
let locked_front_buffer = self.rendering_context.destroy_texture(locked_front_buffer);
debug!("... unlocked chain {:?}", id); debug!("... unlocked chain {:?}", id);
let locked_front_buffer = self.locked_front_buffers.remove(&id)?;
if let Some(locked_front_buffer) =
self.rendering_context.destroy_texture(locked_front_buffer)
{
self.swap_chains self.swap_chains
.get(id)? .get(id)?
.recycle_surface(locked_front_buffer); .recycle_surface(locked_front_buffer);
Some(()) Some(())
} else {
None
}
} }
} }

View file

@ -479,23 +479,6 @@ impl IOCompositor {
self.shutdown_state = ShutdownState::FinishedShuttingDown; 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");
self.rendering_context.invalidate_native_surface();
}
/// 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.
pub fn replace_native_surface(&mut self, native_widget: *mut c_void, coords: DeviceIntSize) {
debug!("Replacing native surface in compositor: {native_widget:?}");
self.rendering_context
.replace_native_surface(native_widget, coords);
}
fn handle_browser_message(&mut self, msg: CompositorMsg) -> bool { fn handle_browser_message(&mut self, msg: CompositorMsg) -> bool {
trace_msg_from_constellation!(msg, "{msg:?}"); trace_msg_from_constellation!(msg, "{msg:?}");

View file

@ -14,7 +14,6 @@ use embedder_traits::{
}; };
use euclid::Scale; use euclid::Scale;
use keyboard_types::{CompositionEvent, KeyboardEvent}; use keyboard_types::{CompositionEvent, KeyboardEvent};
use libc::c_void;
use net::protocols::ProtocolRegistry; use net::protocols::ProtocolRegistry;
use servo_geometry::{DeviceIndependentIntRect, DeviceIndependentIntSize, DeviceIndependentPixel}; use servo_geometry::{DeviceIndependentIntRect, DeviceIndependentIntSize, DeviceIndependentPixel};
use servo_url::ServoUrl; use servo_url::ServoUrl;
@ -119,14 +118,6 @@ pub enum EmbedderEvent {
SetWebViewThrottled(TopLevelBrowsingContextId, bool), SetWebViewThrottled(TopLevelBrowsingContextId, bool),
/// Virtual keyboard was dismissed /// Virtual keyboard was dismissed
IMEDismissed, IMEDismissed,
/// Sent on platforms like Android where the native widget surface can be
/// automatically destroyed by the system, for example when the app
/// is sent to background.
InvalidateNativeSurface,
/// Sent on platforms like Android where system recreates a new surface for
/// the native widget when it is brough back to foreground. This event
/// carries the pointer to the native widget and its new size.
ReplaceNativeSurface(*mut c_void, DeviceIntSize),
/// Sent when new Gamepad information is available. /// Sent when new Gamepad information is available.
Gamepad(GamepadEvent), Gamepad(GamepadEvent),
/// Vertical Synchronization tick /// Vertical Synchronization tick
@ -190,8 +181,6 @@ impl Debug for EmbedderEvent {
EmbedderEvent::SetWebViewThrottled(..) => write!(f, "SetWebViewThrottled"), EmbedderEvent::SetWebViewThrottled(..) => write!(f, "SetWebViewThrottled"),
EmbedderEvent::IMEDismissed => write!(f, "IMEDismissed"), EmbedderEvent::IMEDismissed => write!(f, "IMEDismissed"),
EmbedderEvent::ClearCache => write!(f, "ClearCache"), EmbedderEvent::ClearCache => write!(f, "ClearCache"),
EmbedderEvent::InvalidateNativeSurface => write!(f, "InvalidateNativeSurface"),
EmbedderEvent::ReplaceNativeSurface(..) => write!(f, "ReplaceNativeSurface"),
EmbedderEvent::Gamepad(..) => write!(f, "Gamepad"), EmbedderEvent::Gamepad(..) => write!(f, "Gamepad"),
EmbedderEvent::Vsync => write!(f, "Vsync"), EmbedderEvent::Vsync => write!(f, "Vsync"),
EmbedderEvent::ClipboardAction(_) => write!(f, "ClipboardAction"), EmbedderEvent::ClipboardAction(_) => write!(f, "ClipboardAction"),

View file

@ -22,7 +22,7 @@ layout_2013 = ["dep:layout_thread_2013"]
media-gstreamer = ["servo-media-gstreamer", "gstreamer"] media-gstreamer = ["servo-media-gstreamer", "gstreamer"]
multiview = ["compositing/multiview", "constellation/multiview"] multiview = ["compositing/multiview", "constellation/multiview"]
native-bluetooth = ["bluetooth/native-bluetooth"] native-bluetooth = ["bluetooth/native-bluetooth"]
no-wgl = ["mozangle/egl", "mozangle/build_dlls", "surfman/sm-angle-default"] no-wgl = ["mozangle/egl", "mozangle/build_dlls", "surfman/sm-angle-default", "webrender_traits/no-wgl"]
dynamic_freetype = ["webrender/dynamic_freetype"] dynamic_freetype = ["webrender/dynamic_freetype"]
profilemozjs = ["script/profilemozjs"] profilemozjs = ["script/profilemozjs"]
refcell_backtrace = ["script/refcell_backtrace"] refcell_backtrace = ["script/refcell_backtrace"]

View file

@ -92,20 +92,13 @@ use servo_delegate::DefaultServoDelegate;
use servo_media::player::context::GlContext; use servo_media::player::context::GlContext;
use servo_media::ServoMedia; use servo_media::ServoMedia;
use servo_url::ServoUrl; use servo_url::ServoUrl;
#[cfg(all(target_os = "linux", not(target_env = "ohos")))]
use surfman::platform::generic::multi::connection::NativeConnection as LinuxNativeConnection;
#[cfg(all(target_os = "linux", not(target_env = "ohos")))]
use surfman::platform::generic::multi::context::NativeContext as LinuxNativeContext;
use surfman::{GLApi, GLVersion};
#[cfg(all(target_os = "linux", not(target_env = "ohos")))]
use surfman::{NativeConnection, NativeContext};
#[cfg(feature = "webgpu")] #[cfg(feature = "webgpu")]
pub use webgpu; pub use webgpu;
#[cfg(feature = "webgpu")] #[cfg(feature = "webgpu")]
use webgpu::swapchain::WGPUImageMap; use webgpu::swapchain::WGPUImageMap;
use webrender::{RenderApiSender, ShaderPrecacheFlags, UploadMethod, ONE_TIME_USAGE_HINT}; use webrender::{RenderApiSender, ShaderPrecacheFlags, UploadMethod, ONE_TIME_USAGE_HINT};
use webrender_api::{ColorF, DocumentId, FramePublishId}; use webrender_api::{ColorF, DocumentId, FramePublishId};
use webrender_traits::rendering_context::RenderingContext; use webrender_traits::rendering_context::{GLVersion, RenderingContext};
use webrender_traits::{ use webrender_traits::{
CrossProcessCompositorApi, WebrenderExternalImageHandlers, WebrenderExternalImageRegistry, CrossProcessCompositorApi, WebrenderExternalImageHandlers, WebrenderExternalImageRegistry,
WebrenderImageHandlerType, WebrenderImageHandlerType,
@ -558,58 +551,6 @@ impl Servo {
self.delegate = delegate; self.delegate = delegate;
} }
#[cfg(all(target_os = "linux", not(target_env = "ohos")))]
fn get_native_media_display_and_gl_context(
rendering_context: &Rc<dyn RenderingContext>,
) -> Option<(NativeDisplay, GlContext)> {
let gl_context = match rendering_context.context() {
NativeContext::Default(LinuxNativeContext::Default(native_context)) => {
GlContext::Egl(native_context.egl_context as usize)
},
NativeContext::Default(LinuxNativeContext::Alternate(native_context)) => {
GlContext::Egl(native_context.egl_context as usize)
},
NativeContext::Alternate(_) => return None,
};
let native_display = match rendering_context.connection().native_connection() {
NativeConnection::Default(LinuxNativeConnection::Default(connection)) => {
NativeDisplay::Egl(connection.0 as usize)
},
NativeConnection::Default(LinuxNativeConnection::Alternate(connection)) => {
NativeDisplay::X11(connection.x11_display as usize)
},
NativeConnection::Alternate(_) => return None,
};
Some((native_display, gl_context))
}
// @TODO(victor): https://github.com/servo/media/pull/315
#[cfg(target_os = "windows")]
fn get_native_media_display_and_gl_context(
rendering_context: &Rc<dyn RenderingContext>,
) -> Option<(NativeDisplay, GlContext)> {
#[cfg(feature = "no-wgl")]
{
let gl_context = GlContext::Egl(rendering_context.context().egl_context as usize);
let native_display =
NativeDisplay::Egl(rendering_context.device().egl_display as usize);
Some((native_display, gl_context))
}
#[cfg(not(feature = "no-wgl"))]
None
}
#[cfg(not(any(
target_os = "windows",
all(target_os = "linux", not(target_env = "ohos"))
)))]
fn get_native_media_display_and_gl_context(
_rendering_context: &Rc<dyn RenderingContext>,
) -> Option<(NativeDisplay, GlContext)> {
None
}
fn create_media_window_gl_context( fn create_media_window_gl_context(
external_image_handlers: &mut WebrenderExternalImageHandlers, external_image_handlers: &mut WebrenderExternalImageHandlers,
external_images: Arc<Mutex<WebrenderExternalImageRegistry>>, external_images: Arc<Mutex<WebrenderExternalImageRegistry>>,
@ -627,10 +568,9 @@ impl Servo {
); );
} }
let (native_display, gl_context) = let native_display = rendering_context.gl_display();
match Self::get_native_media_display_and_gl_context(rendering_context) { let gl_context = rendering_context.gl_context();
Some((native_display, gl_context)) => (native_display, gl_context), if let (NativeDisplay::Unknown, GlContext::Unknown) = (&native_display, &gl_context) {
None => {
return ( return (
WindowGLContext { WindowGLContext {
gl_context: GlContext::Unknown, gl_context: GlContext::Unknown,
@ -640,15 +580,22 @@ impl Servo {
}, },
None, None,
); );
}
let gl_api = match rendering_context.gl_version() {
GLVersion::GL(major, minor) => {
if major >= 3 && minor >= 2 {
GlApi::OpenGL3
} else {
GlApi::OpenGL
}
},
GLVersion::GLES(major, _) => {
if major > 1 {
GlApi::Gles2
} else {
GlApi::Gles1
}
}, },
};
let api = rendering_context.connection().gl_api();
let GLVersion { major, minor } = rendering_context.gl_version();
let gl_api = match api {
GLApi::GL if major >= 3 && minor >= 2 => GlApi::OpenGL3,
GLApi::GL => GlApi::OpenGL,
GLApi::GLES if major > 1 => GlApi::Gles2,
GLApi::GLES => GlApi::Gles1,
}; };
assert!(!matches!(gl_context, GlContext::Unknown)); assert!(!matches!(gl_context, GlContext::Unknown));
@ -682,15 +629,6 @@ impl Servo {
) )
} }
}, },
EmbedderEvent::InvalidateNativeSurface => {
self.compositor.borrow_mut().invalidate_native_surface();
},
EmbedderEvent::ReplaceNativeSurface(native_widget, coords) => {
self.compositor
.borrow_mut()
.replace_native_surface(native_widget, coords);
self.compositor.borrow_mut().composite();
},
EmbedderEvent::AllowNavigationResponse(pipeline_id, allowed) => { EmbedderEvent::AllowNavigationResponse(pipeline_id, allowed) => {
let msg = ConstellationMsg::AllowNavigationResponse(pipeline_id, allowed); let msg = ConstellationMsg::AllowNavigationResponse(pipeline_id, allowed);
if let Err(e) = self.constellation_proxy.try_send(msg) { if let Err(e) = self.constellation_proxy.try_send(msg) {

View file

@ -3,7 +3,6 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use std::cell::{Ref, RefCell, RefMut}; use std::cell::{Ref, RefCell, RefMut};
use std::ffi::c_void;
use std::hash::Hash; use std::hash::Hash;
use std::rc::{Rc, Weak}; use std::rc::{Rc, Weak};
use std::time::Duration; use std::time::Duration;
@ -18,7 +17,7 @@ use embedder_traits::{
}; };
use keyboard_types::{CompositionEvent, KeyboardEvent}; use keyboard_types::{CompositionEvent, KeyboardEvent};
use url::Url; use url::Url;
use webrender_api::units::{DeviceIntPoint, DeviceIntSize, DevicePoint, DeviceRect}; use webrender_api::units::{DeviceIntPoint, DevicePoint, DeviceRect};
use webrender_api::ScrollLocation; use webrender_api::ScrollLocation;
use crate::webview_delegate::{DefaultWebViewDelegate, WebViewDelegate}; use crate::webview_delegate::{DefaultWebViewDelegate, WebViewDelegate};
@ -431,24 +430,10 @@ impl WebView {
self.inner().compositor.borrow_mut().capture_webrender(); self.inner().compositor.borrow_mut().capture_webrender();
} }
pub fn invalidate_native_surface(&self) {
self.inner()
.compositor
.borrow_mut()
.invalidate_native_surface();
}
pub fn composite(&self) { pub fn composite(&self) {
self.inner().compositor.borrow_mut().composite(); self.inner().compositor.borrow_mut().composite();
} }
pub fn replace_native_surface(&self, native_widget: *mut c_void, size: DeviceIntSize) {
self.inner()
.compositor
.borrow_mut()
.replace_native_surface(native_widget, size);
}
pub fn toggle_sampling_profiler(&self, rate: Duration, max_duration: Duration) { pub fn toggle_sampling_profiler(&self, rate: Duration, max_duration: Duration) {
self.inner() self.inner()
.constellation_proxy .constellation_proxy

View file

@ -11,6 +11,9 @@ rust-version.workspace = true
name = "webrender_traits" name = "webrender_traits"
path = "lib.rs" path = "lib.rs"
[features]
no-wgl = ["surfman/sm-angle-default"]
[dependencies] [dependencies]
base = { workspace = true } base = { workspace = true }
embedder_traits = { workspace = true } embedder_traits = { workspace = true }
@ -22,5 +25,5 @@ gleam = { workspace = true }
webrender_api = { workspace = true } webrender_api = { workspace = true }
serde = { workspace = true } serde = { workspace = true }
servo_geometry = { path = "../../geometry" } servo_geometry = { path = "../../geometry" }
servo-media = { workspace = true }
surfman = { workspace = true } surfman = { workspace = true }

View file

@ -11,35 +11,35 @@ use std::rc::Rc;
use euclid::default::Size2D; use euclid::default::Size2D;
use gleam::gl; use gleam::gl;
use log::{debug, warn}; use log::{debug, warn};
use servo_media::player::context::{GlContext, NativeDisplay};
use surfman::chains::{PreserveBuffer, SwapChain}; use surfman::chains::{PreserveBuffer, SwapChain};
#[cfg(all(target_os = "linux", not(target_env = "ohos")))]
use surfman::platform::generic::multi::connection::NativeConnection as LinuxNativeConnection;
#[cfg(all(target_os = "linux", not(target_env = "ohos")))]
use surfman::platform::generic::multi::context::NativeContext as LinuxNativeContext;
pub use surfman::Error; pub use surfman::Error;
use surfman::{ use surfman::{
Adapter, Connection, Context, ContextAttributeFlags, ContextAttributes, Device, GLApi, Adapter, Connection, Context, ContextAttributeFlags, ContextAttributes, Device, GLApi,
GLVersion, NativeContext, NativeDevice, NativeWidget, Surface, SurfaceAccess, SurfaceInfo, NativeContext, NativeDevice, NativeWidget, Surface, SurfaceAccess, SurfaceInfo, SurfaceTexture,
SurfaceTexture, SurfaceType, SurfaceType,
}; };
/// Describes the OpenGL version that is requested when a context is created.
pub enum GLVersion {
GL(u8, u8),
GLES(u8, u8),
}
/// The `RenderingContext` trait defines a set of methods for managing /// The `RenderingContext` trait defines a set of methods for managing
/// an OpenGL or GLES rendering context. /// an OpenGL or GLES rendering context.
/// Implementors of this trait are responsible for handling the creation, /// Implementors of this trait are responsible for handling the creation,
/// management, and destruction of the rendering context and its associated /// management, and destruction of the rendering context and its associated
/// resources. /// resources.
pub trait RenderingContext { pub trait RenderingContext {
/// Returns the native OpenGL or GLES device handle
fn device(&self) -> NativeDevice;
/// Returns the native OpenGL or GLES context handle.
fn context(&self) -> NativeContext;
/// Resizes the rendering surface to the given size. /// Resizes the rendering surface to the given size.
fn resize(&self, size: Size2D<i32>); fn resize(&self, size: Size2D<i32>);
/// Presents the rendered frame to the screen. /// Presents the rendered frame to the screen.
fn present(&self); fn present(&self);
/// Binds a native widget to the rendering context.
fn bind_native_surface_to_context(&self, native_widget: NativeWidget);
/// The connection to the display server.
fn connection(&self) -> Connection;
/// Represents a hardware display adapter that can be used for
/// rendering (including the CPU).
fn adapter(&self) -> Adapter;
/// Makes the context the current OpenGL context for this thread. /// Makes the context the current OpenGL context for this thread.
/// After calling this function, it is valid to use OpenGL rendering /// After calling this function, it is valid to use OpenGL rendering
/// commands. /// commands.
@ -50,26 +50,23 @@ pub trait RenderingContext {
fn gl_api(&self) -> Rc<dyn gleam::gl::Gl>; fn gl_api(&self) -> Rc<dyn gleam::gl::Gl>;
/// Describes the OpenGL version that is requested when a context is created. /// Describes the OpenGL version that is requested when a context is created.
fn gl_version(&self) -> GLVersion; fn gl_version(&self) -> GLVersion;
/// Invalidates the native surface by unbinding it from the context. /// Returns the GL Context used by servo media player. Default to `GlContext::Unknown`.
/// This is used only on Android for when the underlying native surface fn gl_context(&self) -> GlContext {
/// can be lost during servo's lifetime. GlContext::Unknown
/// 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. /// Returns the GL Display used by servo media player. Default to `NativeDisplay::Unknown`.
fn invalidate_native_surface(&self); fn gl_display(&self) -> NativeDisplay {
/// Replaces the native surface with a new one. NativeDisplay::Unknown
/// This is used only on Android for when the app moves to foreground }
/// and the system creates a new native surface that needs to bound to
/// the current context.
fn replace_native_surface(
&self,
native_widget: *mut c_void,
coords: euclid::Size2D<i32, webrender_api::units::DevicePixel>,
);
/// Creates a texture from a given surface and returns the surface texture, /// Creates a texture from a given surface and returns the surface texture,
/// the OpenGL texture object, and the size of the surface. /// the OpenGL texture object, and the size of the surface. Default to `None`.
fn create_texture(&self, surface: Surface) -> (SurfaceTexture, u32, Size2D<i32>); fn create_texture(&self, _surface: Surface) -> Option<(SurfaceTexture, u32, Size2D<i32>)> {
/// Destroys the texture and returns the surface. None
fn destroy_texture(&self, surface_texture: SurfaceTexture) -> Surface; }
/// Destroys the texture and returns the surface. Default to `None`.
fn destroy_texture(&self, _surface_texture: SurfaceTexture) -> Option<Surface> {
None
}
} }
/// A rendering context that uses the Surfman library to create and manage /// A rendering context that uses the Surfman library to create and manage
@ -102,17 +99,65 @@ impl Drop for RenderingContextData {
} }
impl RenderingContext for SurfmanRenderingContext { impl RenderingContext for SurfmanRenderingContext {
fn device(&self) -> NativeDevice { fn gl_context(&self) -> GlContext {
self.native_device() #[cfg(all(target_os = "linux", not(target_env = "ohos")))]
{
match self.native_context() {
NativeContext::Default(LinuxNativeContext::Default(native_context)) => {
GlContext::Egl(native_context.egl_context as usize)
},
NativeContext::Default(LinuxNativeContext::Alternate(native_context)) => {
GlContext::Egl(native_context.egl_context as usize)
},
NativeContext::Alternate(_) => GlContext::Unknown,
} }
fn context(&self) -> NativeContext {
self.native_context()
} }
fn connection(&self) -> Connection { #[cfg(target_os = "windows")]
self.connection() {
#[cfg(feature = "no-wgl")]
{
GlContext::Egl(self.native_context().egl_context as usize)
}
#[cfg(not(feature = "no-wgl"))]
GlContext::Unknown
}
#[cfg(not(any(
target_os = "windows",
all(target_os = "linux", not(target_env = "ohos"))
)))]
{
GlContext::Unknown
}
}
fn gl_display(&self) -> NativeDisplay {
#[cfg(all(target_os = "linux", not(target_env = "ohos")))]
{
match self.connection().native_connection() {
surfman::NativeConnection::Default(LinuxNativeConnection::Default(connection)) => {
NativeDisplay::Egl(connection.0 as usize)
},
surfman::NativeConnection::Default(LinuxNativeConnection::Alternate(
connection,
)) => NativeDisplay::X11(connection.x11_display as usize),
surfman::NativeConnection::Alternate(_) => NativeDisplay::Unknown,
}
}
#[cfg(target_os = "windows")]
{
#[cfg(feature = "no-wgl")]
{
NativeDisplay::Egl(self.native_device().egl_display as usize)
}
#[cfg(not(feature = "no-wgl"))]
NativeDisplay::Unknown
}
#[cfg(not(any(
target_os = "windows",
all(target_os = "linux", not(target_env = "ohos"))
)))]
{
NativeDisplay::Unknown
} }
fn adapter(&self) -> Adapter {
self.adapter()
} }
fn resize(&self, size: Size2D<i32>) { fn resize(&self, size: Size2D<i32>) {
if let Err(err) = self.resize(size) { if let Err(err) = self.resize(size) {
@ -124,11 +169,6 @@ impl RenderingContext for SurfmanRenderingContext {
warn!("Failed to present surface: {:?}", err); warn!("Failed to present surface: {:?}", err);
} }
} }
fn bind_native_surface_to_context(&self, native_widget: NativeWidget) {
if let Err(err) = self.bind_native_surface_to_context(native_widget) {
warn!("Failed to bind native surface to context: {:?}", err);
}
}
fn make_current(&self) -> Result<(), Error> { fn make_current(&self) -> Result<(), Error> {
self.make_gl_context_current() self.make_gl_context_current()
} }
@ -155,29 +195,15 @@ impl RenderingContext for SurfmanRenderingContext {
let context = self.0.context.borrow(); let context = self.0.context.borrow();
let descriptor = device.context_descriptor(&context); let descriptor = device.context_descriptor(&context);
let attributes = device.context_descriptor_attributes(&descriptor); let attributes = device.context_descriptor_attributes(&descriptor);
attributes.version let major = attributes.version.major;
} let minor = attributes.version.minor;
fn invalidate_native_surface(&self) { match self.connection().gl_api() {
if let Err(e) = self.unbind_native_surface_from_context() { GLApi::GL => GLVersion::GL(major, minor),
warn!("Unbinding native surface from context failed ({:?})", e); GLApi::GLES => GLVersion::GLES(major, minor),
}
}
#[allow(unsafe_code)]
#[allow(clippy::not_unsafe_ptr_arg_deref)] // It has an unsafe block inside
fn replace_native_surface(
&self,
native_widget: *mut c_void,
coords: euclid::Size2D<i32, webrender_api::units::DevicePixel>,
) {
let connection = self.connection();
let native_widget =
unsafe { connection.create_native_widget_from_ptr(native_widget, coords.to_untyped()) };
if let Err(e) = self.bind_native_surface_to_context(native_widget) {
warn!("Binding native surface to context failed ({:?})", e);
} }
} }
fn create_texture(&self, surface: Surface) -> (SurfaceTexture, u32, Size2D<i32>) { fn create_texture(&self, surface: Surface) -> Option<(SurfaceTexture, u32, Size2D<i32>)> {
let device = &self.0.device.borrow(); let device = &self.0.device.borrow();
let context = &mut self.0.context.borrow_mut(); let context = &mut self.0.context.borrow_mut();
let SurfaceInfo { let SurfaceInfo {
@ -187,16 +213,15 @@ impl RenderingContext for SurfmanRenderingContext {
} = device.surface_info(&surface); } = device.surface_info(&surface);
debug!("... getting texture for surface {:?}", front_buffer_id); debug!("... getting texture for surface {:?}", front_buffer_id);
let surface_texture = device.create_surface_texture(context, surface).unwrap(); let surface_texture = device.create_surface_texture(context, surface).unwrap();
let gl_texture = device.surface_texture_object(&surface_texture); let gl_texture = device
( .surface_texture_object(&surface_texture)
surface_texture, .map(|tex| tex.0.get())
gl_texture.map(|tex| tex.0.get()).unwrap_or(0), .unwrap_or(0);
size, Some((surface_texture, gl_texture, size))
)
} }
fn destroy_texture(&self, surface_texture: SurfaceTexture) -> Surface { fn destroy_texture(&self, surface_texture: SurfaceTexture) -> Option<Surface> {
self.destroy_surface_texture(surface_texture).unwrap() self.destroy_surface_texture(surface_texture).ok()
} }
} }
@ -211,8 +236,8 @@ impl SurfmanRenderingContext {
ContextAttributeFlags::DEPTH | ContextAttributeFlags::DEPTH |
ContextAttributeFlags::STENCIL; ContextAttributeFlags::STENCIL;
let version = match connection.gl_api() { let version = match connection.gl_api() {
GLApi::GLES => GLVersion { major: 3, minor: 0 }, GLApi::GLES => surfman::GLVersion { major: 3, minor: 0 },
GLApi::GL => GLVersion { major: 3, minor: 2 }, GLApi::GL => surfman::GLVersion { major: 3, minor: 2 },
}; };
let context_attributes = ContextAttributes { flags, version }; let context_attributes = ContextAttributes { flags, version };
let context_descriptor = device.create_context_descriptor(&context_attributes)?; let context_descriptor = device.create_context_descriptor(&context_attributes)?;

View file

@ -405,7 +405,9 @@ impl ServoGlue {
} }
pub fn pause_compositor(&mut self) { pub fn pause_compositor(&mut self) {
self.active_webview().invalidate_native_surface(); if let Err(e) = self.rendering_context.unbind_native_surface_from_context() {
warn!("Unbinding native surface from context failed ({:?})", e);
}
self.maybe_perform_updates(); self.maybe_perform_updates();
} }
@ -413,8 +415,17 @@ impl ServoGlue {
if native_surface.is_null() { if native_surface.is_null() {
panic!("null passed for native_surface"); panic!("null passed for native_surface");
} }
self.active_webview() let connection = self.rendering_context.connection();
.replace_native_surface(native_surface, coords.framebuffer); let native_widget = unsafe {
connection
.create_native_widget_from_ptr(native_surface, coords.framebuffer.to_untyped())
};
if let Err(e) = self
.rendering_context
.bind_native_surface_to_context(native_widget)
{
warn!("Binding native surface to context failed ({:?})", e);
}
self.maybe_perform_updates() self.maybe_perform_updates()
} }