aboutsummaryrefslogtreecommitdiffstats
path: root/components/servo/lib.rs
diff options
context:
space:
mode:
authorMartin Robinson <mrobinson@igalia.com>2024-02-03 15:38:48 +0100
committerGitHub <noreply@github.com>2024-02-03 14:38:48 +0000
commitd7d0451424faf1bf9c705068bea1aa8cf582d6ad (patch)
tree58bd9b44b0ba1f86036b322a5155a19eb6e2a913 /components/servo/lib.rs
parentb2fe66f7e4a74eaf9a92c63a062ce67c4d9cc2a5 (diff)
downloadservo-d7d0451424faf1bf9c705068bea1aa8cf582d6ad.tar.gz
servo-d7d0451424faf1bf9c705068bea1aa8cf582d6ad.zip
libservo: Handle GL video decoding setup internally (#31209)
Instead of making the client set up GL video decoding, have this done inside libservo. The details necessary for decoding are fetched via Surfman now. This also removes the setup for the context on Android -- which has no GStreamer support now anyway. In the future, this could be enabled, but should likely be done using Surfman, instead of passing on all these details manually.
Diffstat (limited to 'components/servo/lib.rs')
-rw-r--r--components/servo/lib.rs137
1 files changed, 117 insertions, 20 deletions
diff --git a/components/servo/lib.rs b/components/servo/lib.rs
index 5f1a09d8e71..92278eab1b7 100644
--- a/components/servo/lib.rs
+++ b/components/servo/lib.rs
@@ -17,7 +17,7 @@
//! `Servo` is fed events from a generic type that implements the
//! `WindowMethods` trait.
-use std::borrow::Cow;
+use std::borrow::{BorrowMut, Cow};
use std::cmp::max;
use std::collections::HashMap;
use std::path::PathBuf;
@@ -62,10 +62,11 @@ use euclid::Scale;
use gaol::sandbox::{ChildSandbox, ChildSandboxMethods};
use gfx::font_cache_thread::FontCacheThread;
pub use gfx::rendering_context;
+use gfx::rendering_context::RenderingContext;
pub use gleam::gl;
use ipc_channel::ipc::{self, IpcSender};
use log::{error, trace, warn, Log, Metadata, Record};
-use media::{GLPlayerThreads, WindowGLContext};
+use media::{GLPlayerThreads, GlApi, NativeDisplay, WindowGLContext};
pub use msg::constellation_msg::TopLevelBrowsingContextId;
use msg::constellation_msg::{PipelineNamespace, PipelineNamespaceId};
use net::resource_thread::new_resource_threads;
@@ -78,7 +79,13 @@ use script_traits::{ScriptToConstellationChan, WindowSizeData};
use servo_config::{opts, pref, prefs};
use servo_media::player::context::GlContext;
use servo_media::ServoMedia;
-use surfman::GLApi;
+#[cfg(target_os = "linux")]
+use surfman::platform::generic::multi::connection::NativeConnection as LinuxNativeConnection;
+#[cfg(target_os = "linux")]
+use surfman::platform::generic::multi::context::NativeContext as LinuxNativeContext;
+use surfman::{GLApi, GLVersion};
+#[cfg(target_os = "linux")]
+use surfman::{NativeConnection, NativeContext};
use webrender::{RenderApiSender, ShaderPrecacheFlags};
use webrender_api::{DocumentId, FontInstanceKey, FontKey, ImageKey};
use webrender_traits::{
@@ -388,17 +395,6 @@ where
embedder.register_webxr(&mut webxr_main_thread, embedder_proxy.clone());
}
- let glplayer_threads = match window.get_gl_context() {
- GlContext::Unknown => None,
- _ => {
- let (glplayer_threads, image_handler) =
- GLPlayerThreads::new(external_images.clone());
- external_image_handlers
- .set_handler(image_handler, WebrenderImageHandlerType::Media);
- Some(glplayer_threads)
- },
- };
-
let wgpu_image_handler = webgpu::WGPUExternalImages::new();
let wgpu_image_map = wgpu_image_handler.images.clone();
external_image_handlers.set_handler(
@@ -406,12 +402,11 @@ where
WebrenderImageHandlerType::WebGPU,
);
- let player_context = WindowGLContext {
- gl_context: window.get_gl_context(),
- native_display: window.get_native_display(),
- gl_api: window.get_gl_api(),
- glplayer_chan: glplayer_threads.as_ref().map(GLPlayerThreads::pipeline),
- };
+ let (player_context, glplayer_threads) = Self::create_media_window_gl_context(
+ external_image_handlers.borrow_mut(),
+ external_images.clone(),
+ &rendering_context,
+ );
webrender.set_external_image_handler(external_image_handlers);
@@ -494,6 +489,108 @@ where
}
}
+ #[cfg(target_os = "linux")]
+ fn get_native_media_display_and_gl_context(
+ rendering_context: &RenderingContext,
+ ) -> Option<(NativeDisplay, GlContext)> {
+ let gl_context = match rendering_context.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(_) => 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: &RenderingContext,
+ ) -> Option<(NativeDisplay, GlContext)> {
+ let gl_context = GlContext::Egl(rendering_context.native_context().egl_context as usize);
+ let native_display =
+ NativeDisplay::Egl(rendering_context.native_device().egl_display as usize);
+ Some((native_display, gl_context))
+ }
+
+ #[cfg(not(any(target_os = "windows", target_os = "linux")))]
+ fn get_native_media_display_and_gl_context(
+ _rendering_context: &RenderingContext,
+ ) -> Option<(NativeDisplay, GlContext)> {
+ None
+ }
+
+ fn create_media_window_gl_context(
+ external_image_handlers: &mut WebrenderExternalImageHandlers,
+ external_images: Arc<Mutex<WebrenderExternalImageRegistry>>,
+ rendering_context: &RenderingContext,
+ ) -> (WindowGLContext, Option<GLPlayerThreads>) {
+ if !pref!(media.glvideo.enabled) {
+ return (
+ WindowGLContext {
+ gl_context: GlContext::Unknown,
+ gl_api: GlApi::None,
+ native_display: NativeDisplay::Unknown,
+ glplayer_chan: None,
+ },
+ None,
+ );
+ }
+
+ let (native_display, gl_context) =
+ match Self::get_native_media_display_and_gl_context(rendering_context) {
+ Some((native_display, gl_context)) => (native_display, gl_context),
+ None => {
+ return (
+ WindowGLContext {
+ gl_context: GlContext::Unknown,
+ gl_api: GlApi::None,
+ native_display: NativeDisplay::Unknown,
+ glplayer_chan: None,
+ },
+ None,
+ );
+ },
+ };
+
+ let api = rendering_context.connection().gl_api();
+ let attributes = rendering_context.context_attributes();
+ let GLVersion { major, minor } = attributes.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));
+ let (glplayer_threads, image_handler) = GLPlayerThreads::new(external_images.clone());
+ external_image_handlers.set_handler(image_handler, WebrenderImageHandlerType::Media);
+
+ (
+ WindowGLContext {
+ gl_context,
+ native_display,
+ gl_api,
+ glplayer_chan: Some(GLPlayerThreads::pipeline(&glplayer_threads)),
+ },
+ Some(glplayer_threads),
+ )
+ }
+
fn handle_window_event(&mut self, event: EmbedderEvent) -> bool {
match event {
EmbedderEvent::Idle => {},