mirror of
https://github.com/servo/servo.git
synced 2025-07-22 06:43:40 +01:00
feat: Turn RenderingContext
into a trait (#35052)
* feat: turn RenderingContext into a trait Signed-off-by: DK Liao <dklassic@gmail.com> Add comment and handle drop error Signed-off-by: DK Liao <dklassic@gmail.com> Add doc comment Signed-off-by: DK Liao <dklassic@gmail.com> Allow make_current to propagate Error Signed-off-by: DK Liao <dklassic@gmail.com> Fix all make_current occurances Signed-off-by: DK Liao <dklassic@gmail.com> Move back to Rc<dyn RenderingContext> Signed-off-by: DK Liao <dklassic@gmail.com> fix android/ohos Signed-off-by: DK Liao <dklassic@gmail.com> Fix build Signed-off-by: DK Liao <dklassic@gmail.com> fix android/ohos again Signed-off-by: DK Liao <dklassic@gmail.com> * Fix macOS smoke test Signed-off-by: DK Liao <dklassic@gmail.com> * Add comment for create_texture and destroy_texture Signed-off-by: DK Liao <dklassic@gmail.com> * Improve comments written Signed-off-by: DK Liao <dklassic@gmail.com> --------- Signed-off-by: DK Liao <dklassic@gmail.com>
This commit is contained in:
parent
ac22157491
commit
a0eceee2ed
14 changed files with 236 additions and 112 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -8449,6 +8449,7 @@ dependencies = [
|
|||
"base",
|
||||
"embedder_traits",
|
||||
"euclid",
|
||||
"gleam",
|
||||
"ipc-channel",
|
||||
"libc",
|
||||
"log",
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use std::default::Default;
|
||||
use std::rc::Rc;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use canvas_traits::webgl::{webgl_channel, GlType, WebGLContextId, WebGLMsg, WebGLThreads};
|
||||
|
@ -10,12 +11,12 @@ use euclid::default::Size2D;
|
|||
use fnv::FnvHashMap;
|
||||
use log::debug;
|
||||
use surfman::chains::{SwapChainAPI, SwapChains, SwapChainsAPI};
|
||||
use surfman::{Device, SurfaceInfo, SurfaceTexture};
|
||||
use surfman::{Device, SurfaceTexture};
|
||||
use webrender::RenderApiSender;
|
||||
use webrender_api::DocumentId;
|
||||
use webrender_traits::rendering_context::RenderingContext;
|
||||
use webrender_traits::{
|
||||
RenderingContext, WebrenderExternalImageApi, WebrenderExternalImageRegistry,
|
||||
WebrenderImageSource,
|
||||
WebrenderExternalImageApi, WebrenderExternalImageRegistry, WebrenderImageSource,
|
||||
};
|
||||
#[cfg(feature = "webxr")]
|
||||
use webxr::SurfmanGL as WebXRSurfman;
|
||||
|
@ -34,7 +35,7 @@ pub struct WebGLComm {
|
|||
impl WebGLComm {
|
||||
/// Creates a new `WebGLComm` object.
|
||||
pub fn new(
|
||||
surfman: RenderingContext,
|
||||
rendering_context: Rc<dyn RenderingContext>,
|
||||
webrender_api_sender: RenderApiSender,
|
||||
webrender_doc: DocumentId,
|
||||
external_images: Arc<Mutex<WebrenderExternalImageRegistry>>,
|
||||
|
@ -56,14 +57,14 @@ impl WebGLComm {
|
|||
sender: sender.clone(),
|
||||
receiver,
|
||||
webrender_swap_chains: webrender_swap_chains.clone(),
|
||||
connection: surfman.connection(),
|
||||
adapter: surfman.adapter(),
|
||||
connection: rendering_context.connection(),
|
||||
adapter: rendering_context.adapter(),
|
||||
api_type,
|
||||
#[cfg(feature = "webxr")]
|
||||
webxr_init,
|
||||
};
|
||||
|
||||
let external = WebGLExternalImages::new(surfman, webrender_swap_chains);
|
||||
let external = WebGLExternalImages::new(rendering_context, webrender_swap_chains);
|
||||
|
||||
WebGLThread::run_on_own_thread(init);
|
||||
|
||||
|
@ -78,15 +79,18 @@ impl WebGLComm {
|
|||
|
||||
/// Bridge between the webrender::ExternalImage callbacks and the WebGLThreads.
|
||||
struct WebGLExternalImages {
|
||||
surfman: RenderingContext,
|
||||
rendering_context: Rc<dyn RenderingContext>,
|
||||
swap_chains: SwapChains<WebGLContextId, Device>,
|
||||
locked_front_buffers: FnvHashMap<WebGLContextId, SurfaceTexture>,
|
||||
}
|
||||
|
||||
impl WebGLExternalImages {
|
||||
fn new(surfman: RenderingContext, swap_chains: SwapChains<WebGLContextId, Device>) -> Self {
|
||||
fn new(
|
||||
rendering_context: Rc<dyn RenderingContext>,
|
||||
swap_chains: SwapChains<WebGLContextId, Device>,
|
||||
) -> Self {
|
||||
Self {
|
||||
surfman,
|
||||
rendering_context,
|
||||
swap_chains,
|
||||
locked_front_buffers: FnvHashMap::default(),
|
||||
}
|
||||
|
@ -96,26 +100,17 @@ impl WebGLExternalImages {
|
|||
debug!("... locking chain {:?}", id);
|
||||
let front_buffer = self.swap_chains.get(id)?.take_surface()?;
|
||||
|
||||
let SurfaceInfo {
|
||||
id: front_buffer_id,
|
||||
size,
|
||||
..
|
||||
} = self.surfman.surface_info(&front_buffer);
|
||||
debug!("... getting texture for surface {:?}", front_buffer_id);
|
||||
let front_buffer_texture = self.surfman.create_surface_texture(front_buffer).unwrap();
|
||||
let gl_texture = self.surfman.surface_texture_object(&front_buffer_texture);
|
||||
let (surface_texture, gl_texture, size) =
|
||||
self.rendering_context.create_texture(front_buffer);
|
||||
|
||||
self.locked_front_buffers.insert(id, front_buffer_texture);
|
||||
self.locked_front_buffers.insert(id, surface_texture);
|
||||
|
||||
Some((gl_texture, size))
|
||||
}
|
||||
|
||||
fn unlock_swap_chain(&mut self, id: WebGLContextId) -> Option<()> {
|
||||
let locked_front_buffer = self.locked_front_buffers.remove(&id)?;
|
||||
let locked_front_buffer = self
|
||||
.surfman
|
||||
.destroy_surface_texture(locked_front_buffer)
|
||||
.unwrap();
|
||||
let locked_front_buffer = self.rendering_context.destroy_texture(locked_front_buffer);
|
||||
|
||||
debug!("... unlocked chain {:?}", id);
|
||||
self.swap_chains
|
||||
|
|
|
@ -49,9 +49,9 @@ use webrender_api::{
|
|||
SpatialTreeItemKey, TransformStyle,
|
||||
};
|
||||
use webrender_traits::display_list::{HitTestInfo, ScrollTree};
|
||||
use webrender_traits::rendering_context::RenderingContext;
|
||||
use webrender_traits::{
|
||||
CompositorHitTestResult, CrossProcessCompositorMessage, ImageUpdate, RenderingContext,
|
||||
UntrustedNodeAddress,
|
||||
CompositorHitTestResult, CrossProcessCompositorMessage, ImageUpdate, UntrustedNodeAddress,
|
||||
};
|
||||
|
||||
use crate::gl::RenderTargetInfo;
|
||||
|
@ -165,7 +165,7 @@ pub struct IOCompositor<Window: WindowMethods + ?Sized> {
|
|||
webrender_api: RenderApi,
|
||||
|
||||
/// The surfman instance that webrender targets
|
||||
rendering_context: RenderingContext,
|
||||
rendering_context: Rc<dyn RenderingContext>,
|
||||
|
||||
/// The GL bindings for webrender
|
||||
webrender_gl: Rc<dyn gleam::gl::Gl>,
|
||||
|
@ -412,8 +412,8 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
}
|
||||
|
||||
pub fn deinit(self) {
|
||||
if let Err(err) = self.rendering_context.make_gl_context_current() {
|
||||
warn!("Failed to make GL context current: {:?}", err);
|
||||
if let Err(err) = self.rendering_context.make_current() {
|
||||
warn!("Failed to make the rendering context current: {:?}", err);
|
||||
}
|
||||
self.webrender.deinit();
|
||||
}
|
||||
|
@ -469,27 +469,16 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
/// 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);
|
||||
}
|
||||
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.
|
||||
#[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);
|
||||
}
|
||||
self.rendering_context
|
||||
.replace_native_surface(native_widget, coords);
|
||||
}
|
||||
|
||||
fn handle_browser_message(&mut self, msg: CompositorMsg) -> bool {
|
||||
|
@ -1342,9 +1331,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
let mut transaction = Transaction::new();
|
||||
let size = self.embedder_coordinates.get_viewport();
|
||||
transaction.set_document_view(size);
|
||||
if let Err(e) = self.rendering_context.resize(size.size().to_untyped()) {
|
||||
warn!("Failed to resize surface: {e:?}");
|
||||
}
|
||||
self.rendering_context.resize(size.size().to_untyped());
|
||||
self.webrender_api
|
||||
.send_transaction(self.webrender_document, transaction);
|
||||
}
|
||||
|
@ -2024,9 +2011,8 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
}
|
||||
|
||||
let size = self.embedder_coordinates.framebuffer.to_u32();
|
||||
|
||||
if let Err(err) = self.rendering_context.make_gl_context_current() {
|
||||
warn!("Failed to make GL context current: {:?}", err);
|
||||
if let Err(err) = self.rendering_context.make_current() {
|
||||
warn!("Failed to make the rendering context current: {:?}", err);
|
||||
}
|
||||
self.assert_no_gl_error();
|
||||
|
||||
|
@ -2068,12 +2054,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
.bind();
|
||||
} else {
|
||||
// Bind the webrender framebuffer
|
||||
let framebuffer_object = self
|
||||
.rendering_context
|
||||
.context_surface_info()
|
||||
.unwrap_or(None)
|
||||
.map(|info| info.framebuffer_object)
|
||||
.unwrap_or(0);
|
||||
let framebuffer_object = self.rendering_context.framebuffer_object();
|
||||
self.webrender_gl
|
||||
.bind_framebuffer(gleam::gl::FRAMEBUFFER, framebuffer_object);
|
||||
self.assert_gl_framebuffer_complete();
|
||||
|
@ -2284,9 +2265,7 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
#[cfg(feature = "tracing")]
|
||||
let _span =
|
||||
tracing::trace_span!("Compositor Present Surface", servo_profiling = true).entered();
|
||||
if let Err(err) = self.rendering_context.present() {
|
||||
warn!("Failed to present surface: {:?}", err);
|
||||
}
|
||||
self.rendering_context.present();
|
||||
self.waiting_on_present = false;
|
||||
}
|
||||
|
||||
|
@ -2403,8 +2382,9 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
|||
self.webxr_main_thread.run_one_frame();
|
||||
|
||||
// The WebXR thread may make a different context current
|
||||
let _ = self.rendering_context.make_gl_context_current();
|
||||
|
||||
if let Err(err) = self.rendering_context.make_current() {
|
||||
warn!("Failed to make the rendering context current: {:?}", err);
|
||||
}
|
||||
if !self.pending_scroll_zoom_events.is_empty() {
|
||||
self.process_pending_scroll_events()
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ use crossbeam_channel::Sender;
|
|||
use profile_traits::{mem, time};
|
||||
use webrender::RenderApi;
|
||||
use webrender_api::DocumentId;
|
||||
use webrender_traits::RenderingContext;
|
||||
use webrender_traits::rendering_context::RenderingContext;
|
||||
|
||||
pub use crate::compositor::{CompositeTarget, IOCompositor, ShutdownState};
|
||||
|
||||
|
@ -40,7 +40,7 @@ pub struct InitialCompositorState {
|
|||
pub webrender: webrender::Renderer,
|
||||
pub webrender_document: DocumentId,
|
||||
pub webrender_api: RenderApi,
|
||||
pub rendering_context: RenderingContext,
|
||||
pub rendering_context: Rc<dyn RenderingContext>,
|
||||
pub webrender_gl: Rc<dyn gleam::gl::Gl>,
|
||||
#[cfg(feature = "webxr")]
|
||||
pub webxr_main_thread: webxr::MainThreadRegistry,
|
||||
|
|
|
@ -96,9 +96,10 @@ pub use webgpu;
|
|||
use webgpu::swapchain::WGPUImageMap;
|
||||
use webrender::{RenderApiSender, ShaderPrecacheFlags, UploadMethod, ONE_TIME_USAGE_HINT};
|
||||
use webrender_api::{ColorF, DocumentId, FramePublishId};
|
||||
use webrender_traits::rendering_context::RenderingContext;
|
||||
use webrender_traits::{
|
||||
CrossProcessCompositorApi, RenderingContext, WebrenderExternalImageHandlers,
|
||||
WebrenderExternalImageRegistry, WebrenderImageHandlerType,
|
||||
CrossProcessCompositorApi, WebrenderExternalImageHandlers, WebrenderExternalImageRegistry,
|
||||
WebrenderImageHandlerType,
|
||||
};
|
||||
pub use {
|
||||
background_hang_monitor, base, bluetooth, bluetooth_traits, canvas, canvas_traits, compositing,
|
||||
|
@ -236,7 +237,7 @@ where
|
|||
pub fn new(
|
||||
opts: Opts,
|
||||
preferences: Preferences,
|
||||
rendering_context: RenderingContext,
|
||||
rendering_context: Rc<dyn RenderingContext>,
|
||||
mut embedder: Box<dyn EmbedderMethods>,
|
||||
window: Rc<Window>,
|
||||
user_agent: Option<String>,
|
||||
|
@ -282,23 +283,16 @@ where
|
|||
};
|
||||
|
||||
// Get GL bindings
|
||||
let webrender_gl = match rendering_context.connection().gl_api() {
|
||||
GLApi::GL => unsafe { gl::GlFns::load_with(|s| rendering_context.get_proc_address(s)) },
|
||||
GLApi::GLES => unsafe {
|
||||
gl::GlesFns::load_with(|s| rendering_context.get_proc_address(s))
|
||||
},
|
||||
};
|
||||
let webrender_gl = rendering_context.gl_api();
|
||||
|
||||
// Make sure the gl context is made current.
|
||||
rendering_context.make_gl_context_current().unwrap();
|
||||
if let Err(err) = rendering_context.make_current() {
|
||||
warn!("Failed to make the rendering context current: {:?}", err);
|
||||
}
|
||||
debug_assert_eq!(webrender_gl.get_error(), gleam::gl::NO_ERROR,);
|
||||
|
||||
// Bind the webrender framebuffer
|
||||
let framebuffer_object = rendering_context
|
||||
.context_surface_info()
|
||||
.unwrap_or(None)
|
||||
.map(|info| info.framebuffer_object)
|
||||
.unwrap_or(0);
|
||||
let framebuffer_object = rendering_context.framebuffer_object();
|
||||
webrender_gl.bind_framebuffer(gleam::gl::FRAMEBUFFER, framebuffer_object);
|
||||
|
||||
// Reserving a namespace to create TopLevelBrowsingContextId.
|
||||
|
@ -539,9 +533,9 @@ where
|
|||
|
||||
#[cfg(all(target_os = "linux", not(target_env = "ohos")))]
|
||||
fn get_native_media_display_and_gl_context(
|
||||
rendering_context: &RenderingContext,
|
||||
rendering_context: &Rc<dyn RenderingContext>,
|
||||
) -> Option<(NativeDisplay, GlContext)> {
|
||||
let gl_context = match rendering_context.native_context() {
|
||||
let gl_context = match rendering_context.context() {
|
||||
NativeContext::Default(LinuxNativeContext::Default(native_context)) => {
|
||||
GlContext::Egl(native_context.egl_context as usize)
|
||||
},
|
||||
|
@ -566,14 +560,13 @@ where
|
|||
// @TODO(victor): https://github.com/servo/media/pull/315
|
||||
#[cfg(target_os = "windows")]
|
||||
fn get_native_media_display_and_gl_context(
|
||||
rendering_context: &RenderingContext,
|
||||
rendering_context: &Rc<dyn RenderingContext>,
|
||||
) -> Option<(NativeDisplay, GlContext)> {
|
||||
#[cfg(feature = "no-wgl")]
|
||||
{
|
||||
let gl_context =
|
||||
GlContext::Egl(rendering_context.native_context().egl_context as usize);
|
||||
let gl_context = GlContext::Egl(rendering_context.context().egl_context as usize);
|
||||
let native_display =
|
||||
NativeDisplay::Egl(rendering_context.native_device().egl_display as usize);
|
||||
NativeDisplay::Egl(rendering_context.device().egl_display as usize);
|
||||
Some((native_display, gl_context))
|
||||
}
|
||||
#[cfg(not(feature = "no-wgl"))]
|
||||
|
@ -585,7 +578,7 @@ where
|
|||
all(target_os = "linux", not(target_env = "ohos"))
|
||||
)))]
|
||||
fn get_native_media_display_and_gl_context(
|
||||
_rendering_context: &RenderingContext,
|
||||
_rendering_context: &Rc<dyn RenderingContext>,
|
||||
) -> Option<(NativeDisplay, GlContext)> {
|
||||
None
|
||||
}
|
||||
|
@ -593,7 +586,7 @@ where
|
|||
fn create_media_window_gl_context(
|
||||
external_image_handlers: &mut WebrenderExternalImageHandlers,
|
||||
external_images: Arc<Mutex<WebrenderExternalImageRegistry>>,
|
||||
rendering_context: &RenderingContext,
|
||||
rendering_context: &Rc<dyn RenderingContext>,
|
||||
) -> (WindowGLContext, Option<GLPlayerThreads>) {
|
||||
if !pref!(media_glvideo_enabled) {
|
||||
return (
|
||||
|
@ -622,10 +615,8 @@ where
|
|||
);
|
||||
},
|
||||
};
|
||||
|
||||
let api = rendering_context.connection().gl_api();
|
||||
let attributes = rendering_context.context_attributes();
|
||||
let GLVersion { major, minor } = attributes.version;
|
||||
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,
|
||||
|
|
|
@ -18,6 +18,7 @@ euclid = { workspace = true }
|
|||
ipc-channel = { workspace = true }
|
||||
log = { workspace = true }
|
||||
libc = { workspace = true }
|
||||
gleam = { workspace = true }
|
||||
webrender_api = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
servo_geometry = { path = "../../geometry" }
|
||||
|
|
|
@ -28,7 +28,7 @@ use webrender_api::{
|
|||
ImageKey, NativeFontHandle, PipelineId as WebRenderPipelineId,
|
||||
};
|
||||
|
||||
pub use crate::rendering_context::RenderingContext;
|
||||
pub use crate::rendering_context::SurfmanRenderingContext;
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub enum CrossProcessCompositorMessage {
|
||||
|
|
|
@ -9,17 +9,79 @@ use std::ffi::c_void;
|
|||
use std::rc::Rc;
|
||||
|
||||
use euclid::default::Size2D;
|
||||
use gleam::gl;
|
||||
use log::{debug, warn};
|
||||
use surfman::chains::{PreserveBuffer, SwapChain};
|
||||
pub use surfman::Error;
|
||||
use surfman::{
|
||||
Adapter, Connection, Context, ContextAttributeFlags, ContextAttributes, Device, Error, GLApi,
|
||||
Adapter, Connection, Context, ContextAttributeFlags, ContextAttributes, Device, GLApi,
|
||||
GLVersion, NativeContext, NativeDevice, NativeWidget, Surface, SurfaceAccess, SurfaceInfo,
|
||||
SurfaceTexture, SurfaceType,
|
||||
};
|
||||
|
||||
/// A Servo rendering context, which holds all of the information needed
|
||||
/// to render Servo's layout, and bridges WebRender and surfman.
|
||||
/// The `RenderingContext` trait defines a set of methods for managing
|
||||
/// an OpenGL or GLES rendering context.
|
||||
/// Implementors of this trait are responsible for handling the creation,
|
||||
/// management, and destruction of the rendering context and its associated
|
||||
/// resources.
|
||||
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.
|
||||
fn resize(&self, size: Size2D<i32>);
|
||||
/// Presents the rendered frame to the screen.
|
||||
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.
|
||||
/// After calling this function, it is valid to use OpenGL rendering
|
||||
/// commands.
|
||||
fn make_current(&self) -> Result<(), Error>;
|
||||
/// Returns the OpenGL framebuffer object needed to render to the surface.
|
||||
fn framebuffer_object(&self) -> u32;
|
||||
/// Returns the OpenGL or GLES API.
|
||||
fn gl_api(&self) -> Rc<dyn gleam::gl::Gl>;
|
||||
/// Describes the OpenGL version that is requested when a context is created.
|
||||
fn gl_version(&self) -> GLVersion;
|
||||
/// Invalidates the native surface by unbinding it from the context.
|
||||
/// This is used only on Android for when the underlying native surface
|
||||
/// can be lost during servo's lifetime.
|
||||
/// 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.
|
||||
fn invalidate_native_surface(&self);
|
||||
/// Replaces the native surface with a new one.
|
||||
/// 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,
|
||||
/// the OpenGL texture object, and the size of the surface.
|
||||
fn create_texture(&self, surface: Surface) -> (SurfaceTexture, u32, Size2D<i32>);
|
||||
/// Destroys the texture and returns the surface.
|
||||
fn destroy_texture(&self, surface_texture: SurfaceTexture) -> Surface;
|
||||
}
|
||||
|
||||
/// A rendering context that uses the Surfman library to create and manage
|
||||
/// the OpenGL context and surface. This struct provides the default implementation
|
||||
/// of the `RenderingContext` trait, handling the creation, management, and destruction
|
||||
/// of the rendering context and its associated resources.
|
||||
///
|
||||
/// The `SurfmanRenderingContext` struct encapsulates the necessary data and methods
|
||||
/// to interact with the Surfman library, including creating surfaces, binding surfaces,
|
||||
/// resizing surfaces, presenting rendered frames, and managing the OpenGL context state.
|
||||
#[derive(Clone)]
|
||||
pub struct RenderingContext(Rc<RenderingContextData>);
|
||||
pub struct SurfmanRenderingContext(Rc<RenderingContextData>);
|
||||
|
||||
struct RenderingContextData {
|
||||
device: RefCell<Device>,
|
||||
|
@ -39,7 +101,101 @@ impl Drop for RenderingContextData {
|
|||
}
|
||||
}
|
||||
|
||||
impl RenderingContext {
|
||||
impl RenderingContext for SurfmanRenderingContext {
|
||||
fn device(&self) -> NativeDevice {
|
||||
self.native_device()
|
||||
}
|
||||
fn context(&self) -> NativeContext {
|
||||
self.native_context()
|
||||
}
|
||||
fn connection(&self) -> Connection {
|
||||
self.connection()
|
||||
}
|
||||
fn adapter(&self) -> Adapter {
|
||||
self.adapter()
|
||||
}
|
||||
fn resize(&self, size: Size2D<i32>) {
|
||||
if let Err(err) = self.resize(size) {
|
||||
warn!("Failed to resize surface: {:?}", err);
|
||||
}
|
||||
}
|
||||
fn present(&self) {
|
||||
if let Err(err) = self.present() {
|
||||
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> {
|
||||
self.make_gl_context_current()
|
||||
}
|
||||
fn framebuffer_object(&self) -> u32 {
|
||||
self.context_surface_info()
|
||||
.unwrap_or(None)
|
||||
.map(|info| info.framebuffer_object)
|
||||
.unwrap_or(0)
|
||||
}
|
||||
#[allow(unsafe_code)]
|
||||
fn gl_api(&self) -> Rc<dyn gleam::gl::Gl> {
|
||||
let context = self.0.context.borrow();
|
||||
let device = self.0.device.borrow();
|
||||
match self.connection().gl_api() {
|
||||
GLApi::GL => unsafe { gl::GlFns::load_with(|s| device.get_proc_address(&context, s)) },
|
||||
GLApi::GLES => unsafe {
|
||||
gl::GlesFns::load_with(|s| device.get_proc_address(&context, s))
|
||||
},
|
||||
}
|
||||
}
|
||||
fn gl_version(&self) -> GLVersion {
|
||||
let device = self.0.device.borrow();
|
||||
let context = self.0.context.borrow();
|
||||
let descriptor = device.context_descriptor(&context);
|
||||
let attributes = device.context_descriptor_attributes(&descriptor);
|
||||
attributes.version
|
||||
}
|
||||
fn invalidate_native_surface(&self) {
|
||||
if let Err(e) = self.unbind_native_surface_from_context() {
|
||||
warn!("Unbinding native surface from context failed ({:?})", e);
|
||||
}
|
||||
}
|
||||
#[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>) {
|
||||
let device = &self.0.device.borrow();
|
||||
let context = &mut self.0.context.borrow_mut();
|
||||
let SurfaceInfo {
|
||||
id: front_buffer_id,
|
||||
size,
|
||||
..
|
||||
} = device.surface_info(&surface);
|
||||
debug!("... getting texture for surface {:?}", front_buffer_id);
|
||||
let surface_texture = device.create_surface_texture(context, surface).unwrap();
|
||||
let gl_texture = device.surface_texture_object(&surface_texture);
|
||||
(surface_texture, gl_texture, size)
|
||||
}
|
||||
|
||||
fn destroy_texture(&self, surface_texture: SurfaceTexture) -> Surface {
|
||||
self.destroy_surface_texture(surface_texture).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl SurfmanRenderingContext {
|
||||
pub fn create(
|
||||
connection: &Connection,
|
||||
adapter: &Adapter,
|
||||
|
@ -82,7 +238,7 @@ impl RenderingContext {
|
|||
context,
|
||||
swap_chain,
|
||||
};
|
||||
Ok(RenderingContext(Rc::new(data)))
|
||||
Ok(SurfmanRenderingContext(Rc::new(data)))
|
||||
}
|
||||
|
||||
pub fn create_surface(
|
||||
|
|
|
@ -20,7 +20,7 @@ use servo::config::prefs::Preferences;
|
|||
use servo::embedder_traits::EventLoopWaker;
|
||||
use servo::servo_config::pref;
|
||||
use servo::url::ServoUrl;
|
||||
use servo::webrender_traits::RenderingContext;
|
||||
use servo::webrender_traits::SurfmanRenderingContext;
|
||||
use servo::Servo;
|
||||
use surfman::Connection;
|
||||
use webxr::glwindow::GlWindowDiscovery;
|
||||
|
@ -113,7 +113,7 @@ impl App {
|
|||
let adapter = connection
|
||||
.create_software_adapter()
|
||||
.expect("Failed to create adapter");
|
||||
RenderingContext::create(
|
||||
SurfmanRenderingContext::create(
|
||||
&connection,
|
||||
&adapter,
|
||||
Some(self.opts.initial_window_size.to_untyped().to_i32()),
|
||||
|
@ -129,7 +129,7 @@ impl App {
|
|||
let adapter = connection
|
||||
.create_adapter()
|
||||
.expect("Failed to create adapter");
|
||||
RenderingContext::create(&connection, &adapter, None)
|
||||
SurfmanRenderingContext::create(&connection, &adapter, None)
|
||||
.expect("Failed to create WR surfman")
|
||||
};
|
||||
|
||||
|
@ -206,7 +206,7 @@ impl App {
|
|||
let mut servo = Servo::new(
|
||||
self.opts.clone(),
|
||||
self.preferences.clone(),
|
||||
rendering_context,
|
||||
Rc::new(rendering_context),
|
||||
embedder,
|
||||
window.clone(),
|
||||
self.servo_shell_preferences.user_agent.clone(),
|
||||
|
|
|
@ -22,7 +22,7 @@ use servo::servo_config::pref;
|
|||
use servo::servo_geometry::DeviceIndependentPixel;
|
||||
use servo::webrender_api::units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixel};
|
||||
use servo::webrender_api::ScrollLocation;
|
||||
use servo::webrender_traits::RenderingContext;
|
||||
use servo::webrender_traits::SurfmanRenderingContext;
|
||||
use surfman::{Context, Device, SurfaceType};
|
||||
use winit::dpi::{LogicalSize, PhysicalPosition, PhysicalSize};
|
||||
use winit::event::{ElementState, KeyEvent, MouseButton, MouseScrollDelta, TouchPhase};
|
||||
|
@ -59,7 +59,7 @@ pub struct Window {
|
|||
impl Window {
|
||||
pub fn new(
|
||||
opts: &Opts,
|
||||
rendering_context: &RenderingContext,
|
||||
rendering_context: &SurfmanRenderingContext,
|
||||
window_size: Size2D<u32, DeviceIndependentPixel>,
|
||||
event_loop: &ActiveEventLoop,
|
||||
no_native_titlebar: bool,
|
||||
|
|
|
@ -25,7 +25,7 @@ use servo::script_traits::TraversalDirection;
|
|||
use servo::servo_geometry::DeviceIndependentPixel;
|
||||
use servo::servo_url::ServoUrl;
|
||||
use servo::webrender_api::units::DevicePixel;
|
||||
use servo::webrender_traits::RenderingContext;
|
||||
use servo::webrender_traits::SurfmanRenderingContext;
|
||||
use servo::TopLevelBrowsingContextId;
|
||||
use winit::event::{ElementState, MouseButton, WindowEvent};
|
||||
use winit::event_loop::ActiveEventLoop;
|
||||
|
@ -79,7 +79,7 @@ fn truncate_with_ellipsis(input: &str, max_length: usize) -> String {
|
|||
|
||||
impl Minibrowser {
|
||||
pub fn new(
|
||||
rendering_context: &RenderingContext,
|
||||
rendering_context: &SurfmanRenderingContext,
|
||||
event_loop: &ActiveEventLoop,
|
||||
initial_url: ServoUrl,
|
||||
) -> Self {
|
||||
|
|
|
@ -18,7 +18,7 @@ pub use servo::embedder_traits::EventLoopWaker;
|
|||
pub use servo::embedder_traits::{InputMethodType, MediaSessionPlaybackState, PromptResult};
|
||||
use servo::servo_url::ServoUrl;
|
||||
pub use servo::webrender_api::units::DeviceIntRect;
|
||||
use servo::webrender_traits::RenderingContext;
|
||||
use servo::webrender_traits::SurfmanRenderingContext;
|
||||
use servo::{self, Servo};
|
||||
use surfman::{Connection, SurfaceType};
|
||||
|
||||
|
@ -98,7 +98,7 @@ pub fn init(
|
|||
SurfaceType::Widget { native_widget }
|
||||
},
|
||||
};
|
||||
let rendering_context = RenderingContext::create(&connection, &adapter, None)
|
||||
let rendering_context = SurfmanRenderingContext::create(&connection, &adapter, None)
|
||||
.or(Err("Failed to create surface manager"))?;
|
||||
let surface = rendering_context
|
||||
.create_surface(surface_type)
|
||||
|
@ -122,7 +122,7 @@ pub fn init(
|
|||
let servo = Servo::new(
|
||||
opts,
|
||||
preferences,
|
||||
rendering_context.clone(),
|
||||
Rc::new(rendering_context.clone()),
|
||||
embedder_callbacks,
|
||||
window_callbacks.clone(),
|
||||
None,
|
||||
|
|
|
@ -18,7 +18,7 @@ use servo::embedder_traits::resources;
|
|||
pub use servo::embedder_traits::EventLoopWaker;
|
||||
use servo::euclid::Size2D;
|
||||
use servo::servo_url::ServoUrl;
|
||||
use servo::webrender_traits::RenderingContext;
|
||||
use servo::webrender_traits::SurfmanRenderingContext;
|
||||
use servo::{self, Servo};
|
||||
use surfman::{Connection, SurfaceType};
|
||||
use xcomponent_sys::{OH_NativeXComponent, OH_NativeXComponent_GetXComponentSize};
|
||||
|
@ -93,7 +93,7 @@ pub fn init(
|
|||
let surface_type = SurfaceType::Widget { native_widget };
|
||||
|
||||
info!("Creating rendering context");
|
||||
let rendering_context = RenderingContext::create(&connection, &adapter, None)
|
||||
let rendering_context = SurfmanRenderingContext::create(&connection, &adapter, None)
|
||||
.or(Err("Failed to create surface manager"))?;
|
||||
let surface = rendering_context
|
||||
.create_surface(surface_type)
|
||||
|
@ -119,7 +119,7 @@ pub fn init(
|
|||
let servo = Servo::new(
|
||||
opts,
|
||||
preferences,
|
||||
rendering_context.clone(),
|
||||
Rc::new(rendering_context.clone()),
|
||||
embedder_callbacks,
|
||||
window_callbacks.clone(),
|
||||
None, /* user_agent */
|
||||
|
|
|
@ -27,7 +27,7 @@ use servo::script_traits::{
|
|||
use servo::servo_geometry::DeviceIndependentPixel;
|
||||
use servo::webrender_api::units::DevicePixel;
|
||||
use servo::webrender_api::ScrollLocation;
|
||||
use servo::webrender_traits::RenderingContext;
|
||||
use servo::webrender_traits::SurfmanRenderingContext;
|
||||
use servo::{Servo, TopLevelBrowsingContextId};
|
||||
|
||||
use crate::egl::host_trait::HostTrait;
|
||||
|
@ -79,7 +79,7 @@ impl ServoWindowCallbacks {
|
|||
pub struct WebView {}
|
||||
|
||||
pub struct ServoGlue {
|
||||
rendering_context: RenderingContext,
|
||||
rendering_context: SurfmanRenderingContext,
|
||||
servo: Servo<ServoWindowCallbacks>,
|
||||
batch_mode: bool,
|
||||
need_present: bool,
|
||||
|
@ -106,7 +106,7 @@ pub struct ServoGlue {
|
|||
#[allow(unused)]
|
||||
impl ServoGlue {
|
||||
pub(super) fn new(
|
||||
rendering_context: RenderingContext,
|
||||
rendering_context: SurfmanRenderingContext,
|
||||
servo: Servo<ServoWindowCallbacks>,
|
||||
callbacks: Rc<ServoWindowCallbacks>,
|
||||
servoshell_preferences: ServoShellPreferences,
|
||||
|
@ -146,7 +146,7 @@ impl ServoGlue {
|
|||
|
||||
/// Returns the webrender surface management integration interface.
|
||||
/// This provides the embedder access to the current front buffer.
|
||||
pub fn surfman(&self) -> RenderingContext {
|
||||
pub fn surfman(&self) -> SurfmanRenderingContext {
|
||||
self.rendering_context.clone()
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue