mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2024-11-25 21:11:00 +00:00
gtk4: Add support for GL on Windows
This implements all the workarounds for Windows-specific complications that the GTK GStreamer mediafile implementation also does. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1255>
This commit is contained in:
parent
2be14b95b3
commit
dcb80ac105
4 changed files with 216 additions and 26 deletions
|
@ -262,6 +262,10 @@ if get_option('gtk4').allowed()
|
||||||
if 'glx' in gl_platforms
|
if 'glx' in gl_platforms
|
||||||
gtk4_features += 'x11glx'
|
gtk4_features += 'x11glx'
|
||||||
endif
|
endif
|
||||||
|
elif host_system == 'windows'
|
||||||
|
if 'egl' in gl_platforms
|
||||||
|
gtk4_features += 'winegl'
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
plugins += {'gtk4': {
|
plugins += {'gtk4': {
|
||||||
'library': 'libgstgtk4',
|
'library': 'libgstgtk4',
|
||||||
|
|
|
@ -28,6 +28,12 @@ once_cell = "1.0"
|
||||||
gtk = { package = "gtk4", git = "https://github.com/gtk-rs/gtk4-rs", features = ["v4_6"] }
|
gtk = { package = "gtk4", git = "https://github.com/gtk-rs/gtk4-rs", features = ["v4_6"] }
|
||||||
gst_gl = { package = "gstreamer-gl", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs", features = ["v1_16"] }
|
gst_gl = { package = "gstreamer-gl", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs", features = ["v1_16"] }
|
||||||
|
|
||||||
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
|
gtk = { package = "gtk4", git = "https://github.com/gtk-rs/gtk4-rs", features = ["v4_6"] }
|
||||||
|
gst_gl = { package = "gstreamer-gl", git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs", features = ["v1_20"] }
|
||||||
|
gdk_win32 = { package = "gdk4-win32", git = "https://github.com/gtk-rs/gtk4-rs", features = ["v4_4"]}
|
||||||
|
windows-sys = { version = "0.42", features = ["Win32_Graphics_OpenGL", "Win32_Foundation", "Win32_Graphics_Gdi"] }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "gstgtk4"
|
name = "gstgtk4"
|
||||||
crate-type = ["cdylib", "rlib"]
|
crate-type = ["cdylib", "rlib"]
|
||||||
|
@ -42,6 +48,7 @@ static = []
|
||||||
wayland = ["gtk/v4_6", "gdk_wayland", "gst_gl", "gst_gl_wayland"]
|
wayland = ["gtk/v4_6", "gdk_wayland", "gst_gl", "gst_gl_wayland"]
|
||||||
x11glx = ["gtk/v4_6", "gdk_x11", "gst_gl", "gst_gl_x11"]
|
x11glx = ["gtk/v4_6", "gdk_x11", "gst_gl", "gst_gl_x11"]
|
||||||
x11egl = ["gtk/v4_6", "gdk_x11", "gst_gl", "gst_gl_egl"]
|
x11egl = ["gtk/v4_6", "gdk_x11", "gst_gl", "gst_gl_egl"]
|
||||||
|
winegl = ["gdk_win32/egl", "gst_gl_egl"]
|
||||||
capi = []
|
capi = []
|
||||||
doc = ["gst/v1_18"]
|
doc = ["gst/v1_18"]
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
use gst_video::prelude::*;
|
use gst_video::prelude::*;
|
||||||
|
|
||||||
#[cfg(any(target_os = "macos", feature = "gst_gl"))]
|
#[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))]
|
||||||
use gst_gl::prelude::*;
|
use gst_gl::prelude::*;
|
||||||
use gtk::{gdk, glib};
|
use gtk::{gdk, glib};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
|
@ -20,7 +20,7 @@ use std::collections::{HashMap, HashSet};
|
||||||
pub(crate) struct Frame {
|
pub(crate) struct Frame {
|
||||||
frame: gst_video::VideoFrame<gst_video::video_frame::Readable>,
|
frame: gst_video::VideoFrame<gst_video::video_frame::Readable>,
|
||||||
overlays: Vec<Overlay>,
|
overlays: Vec<Overlay>,
|
||||||
#[cfg(any(target_os = "macos", feature = "gst_gl"))]
|
#[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))]
|
||||||
wrapped_context: Option<gst_gl::GLContext>,
|
wrapped_context: Option<gst_gl::GLContext>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ fn video_frame_to_memory_texture(
|
||||||
(texture, pixel_aspect_ratio)
|
(texture, pixel_aspect_ratio)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(target_os = "macos", feature = "gst_gl"))]
|
#[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))]
|
||||||
fn video_frame_to_gl_texture(
|
fn video_frame_to_gl_texture(
|
||||||
frame: gst_video::VideoFrame<gst_video::video_frame::Readable>,
|
frame: gst_video::VideoFrame<gst_video::video_frame::Readable>,
|
||||||
cached_textures: &mut HashMap<usize, gdk::Texture>,
|
cached_textures: &mut HashMap<usize, gdk::Texture>,
|
||||||
|
@ -150,11 +150,11 @@ impl Frame {
|
||||||
let width = self.frame.width();
|
let width = self.frame.width();
|
||||||
let height = self.frame.height();
|
let height = self.frame.height();
|
||||||
let (texture, pixel_aspect_ratio) = {
|
let (texture, pixel_aspect_ratio) = {
|
||||||
#[cfg(not(any(target_os = "macos", feature = "gst_gl")))]
|
#[cfg(not(any(target_os = "macos", target_os = "windows", feature = "gst_gl")))]
|
||||||
{
|
{
|
||||||
video_frame_to_memory_texture(self.frame, cached_textures, &mut used_textures)
|
video_frame_to_memory_texture(self.frame, cached_textures, &mut used_textures)
|
||||||
}
|
}
|
||||||
#[cfg(any(target_os = "macos", feature = "gst_gl"))]
|
#[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))]
|
||||||
{
|
{
|
||||||
if let (Some(gdk_ctx), Some(wrapped_ctx)) =
|
if let (Some(gdk_ctx), Some(wrapped_ctx)) =
|
||||||
(gdk_context, self.wrapped_context.as_ref())
|
(gdk_context, self.wrapped_context.as_ref())
|
||||||
|
@ -210,11 +210,11 @@ impl Frame {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
buffer: &gst::Buffer,
|
buffer: &gst::Buffer,
|
||||||
info: &gst_video::VideoInfo,
|
info: &gst_video::VideoInfo,
|
||||||
#[cfg(any(target_os = "macos", feature = "gst_gl"))] wrapped_context: Option<
|
#[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))] wrapped_context: Option<
|
||||||
&gst_gl::GLContext,
|
&gst_gl::GLContext,
|
||||||
>,
|
>,
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
#[cfg(not(any(target_os = "macos", feature = "gst_gl")))]
|
#[cfg(not(any(target_os = "macos", target_os = "windows", feature = "gst_gl")))]
|
||||||
wrapped_context: Option<&()>,
|
wrapped_context: Option<&()>,
|
||||||
) -> Result<Self, gst::FlowError> {
|
) -> Result<Self, gst::FlowError> {
|
||||||
// Empty buffers get filtered out in show_frame
|
// Empty buffers get filtered out in show_frame
|
||||||
|
@ -222,7 +222,7 @@ impl Frame {
|
||||||
|
|
||||||
let mut frame;
|
let mut frame;
|
||||||
|
|
||||||
#[cfg(not(any(target_os = "macos", feature = "gst_gl")))]
|
#[cfg(not(any(target_os = "macos", target_os = "windows", feature = "gst_gl")))]
|
||||||
{
|
{
|
||||||
frame = Self {
|
frame = Self {
|
||||||
frame: gst_video::VideoFrame::from_buffer_readable(buffer.clone(), info)
|
frame: gst_video::VideoFrame::from_buffer_readable(buffer.clone(), info)
|
||||||
|
@ -230,7 +230,7 @@ impl Frame {
|
||||||
overlays: vec![],
|
overlays: vec![],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#[cfg(any(target_os = "macos", feature = "gst_gl"))]
|
#[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))]
|
||||||
{
|
{
|
||||||
// Check we received a buffer with GL memory and if the context of that memory
|
// Check we received a buffer with GL memory and if the context of that memory
|
||||||
// can share with the wrapped context around the GDK GL context.
|
// can share with the wrapped context around the GDK GL context.
|
||||||
|
|
|
@ -26,15 +26,15 @@ use std::sync::{Mutex, MutexGuard};
|
||||||
|
|
||||||
use crate::utils;
|
use crate::utils;
|
||||||
|
|
||||||
#[cfg(any(target_os = "macos", feature = "gst_gl"))]
|
#[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))]
|
||||||
use gst_gl::prelude::GLContextExt as GstGLContextExt;
|
use gst_gl::prelude::GLContextExt as GstGLContextExt;
|
||||||
#[cfg(any(target_os = "macos", feature = "gst_gl"))]
|
#[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))]
|
||||||
use gst_gl::prelude::*;
|
use gst_gl::prelude::*;
|
||||||
|
|
||||||
// Global GL context that is created by the first sink and kept around until the end of the
|
// Global GL context that is created by the first sink and kept around until the end of the
|
||||||
// process. This is provided to other elements in the pipeline to make sure they create GL contexts
|
// process. This is provided to other elements in the pipeline to make sure they create GL contexts
|
||||||
// that are sharing with the GTK GL context.
|
// that are sharing with the GTK GL context.
|
||||||
#[cfg(any(target_os = "macos", feature = "gst_gl"))]
|
#[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))]
|
||||||
enum GLContext {
|
enum GLContext {
|
||||||
Uninitialized,
|
Uninitialized,
|
||||||
Unsupported,
|
Unsupported,
|
||||||
|
@ -45,7 +45,7 @@ enum GLContext {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(target_os = "macos", feature = "gst_gl"))]
|
#[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))]
|
||||||
static GL_CONTEXT: Mutex<GLContext> = Mutex::new(GLContext::Uninitialized);
|
static GL_CONTEXT: Mutex<GLContext> = Mutex::new(GLContext::Uninitialized);
|
||||||
|
|
||||||
static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
|
static CAT: Lazy<gst::DebugCategory> = Lazy::new(|| {
|
||||||
|
@ -154,12 +154,12 @@ impl ElementImpl for PaintableSink {
|
||||||
|
|
||||||
for features in [
|
for features in [
|
||||||
None,
|
None,
|
||||||
#[cfg(any(target_os = "macos", feature = "gst_gl"))]
|
#[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))]
|
||||||
Some(gst::CapsFeatures::new([
|
Some(gst::CapsFeatures::new([
|
||||||
"memory:GLMemory",
|
"memory:GLMemory",
|
||||||
"meta:GstVideoOverlayComposition",
|
"meta:GstVideoOverlayComposition",
|
||||||
])),
|
])),
|
||||||
#[cfg(any(target_os = "macos", feature = "gst_gl"))]
|
#[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))]
|
||||||
Some(gst::CapsFeatures::new(["memory:GLMemory"])),
|
Some(gst::CapsFeatures::new(["memory:GLMemory"])),
|
||||||
Some(gst::CapsFeatures::new([
|
Some(gst::CapsFeatures::new([
|
||||||
"memory:SystemMemory",
|
"memory:SystemMemory",
|
||||||
|
@ -225,7 +225,7 @@ impl ElementImpl for PaintableSink {
|
||||||
// Notify the pipeline about the GL display and wrapped context so that any other
|
// Notify the pipeline about the GL display and wrapped context so that any other
|
||||||
// elements in the pipeline ideally use the same / create GL contexts that are
|
// elements in the pipeline ideally use the same / create GL contexts that are
|
||||||
// sharing with this one.
|
// sharing with this one.
|
||||||
#[cfg(any(target_os = "macos", feature = "gst_gl"))]
|
#[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))]
|
||||||
{
|
{
|
||||||
let gl_context = GL_CONTEXT.lock().unwrap();
|
let gl_context = GL_CONTEXT.lock().unwrap();
|
||||||
if let GLContext::Initialized {
|
if let GLContext::Initialized {
|
||||||
|
@ -331,7 +331,7 @@ impl BaseSinkImpl for PaintableSink {
|
||||||
// TODO: Provide a preferred "window size" here for higher-resolution rendering
|
// TODO: Provide a preferred "window size" here for higher-resolution rendering
|
||||||
query.add_allocation_meta::<gst_video::VideoOverlayCompositionMeta>(None);
|
query.add_allocation_meta::<gst_video::VideoOverlayCompositionMeta>(None);
|
||||||
|
|
||||||
#[cfg(any(target_os = "macos", feature = "gst_gl"))]
|
#[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))]
|
||||||
{
|
{
|
||||||
if let GLContext::Initialized {
|
if let GLContext::Initialized {
|
||||||
wrapped_context, ..
|
wrapped_context, ..
|
||||||
|
@ -352,7 +352,7 @@ impl BaseSinkImpl for PaintableSink {
|
||||||
gst::log!(CAT, imp: self, "Handling query {:?}", query);
|
gst::log!(CAT, imp: self, "Handling query {:?}", query);
|
||||||
|
|
||||||
match query.view_mut() {
|
match query.view_mut() {
|
||||||
#[cfg(any(target_os = "macos", feature = "gst_gl"))]
|
#[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))]
|
||||||
gst::QueryViewMut::Context(q) => {
|
gst::QueryViewMut::Context(q) => {
|
||||||
// Avoid holding the locks while we respond to the query
|
// Avoid holding the locks while we respond to the query
|
||||||
// The objects are ref-counted anyway.
|
// The objects are ref-counted anyway.
|
||||||
|
@ -408,11 +408,11 @@ impl VideoSinkImpl for PaintableSink {
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let wrapped_context = {
|
let wrapped_context = {
|
||||||
#[cfg(not(any(target_os = "macos", feature = "gst_gl")))]
|
#[cfg(not(any(target_os = "macos", target_os = "windows", feature = "gst_gl")))]
|
||||||
{
|
{
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
#[cfg(any(target_os = "macos", feature = "gst_gl"))]
|
#[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))]
|
||||||
{
|
{
|
||||||
let gl_context = GL_CONTEXT.lock().unwrap();
|
let gl_context = GL_CONTEXT.lock().unwrap();
|
||||||
if let GLContext::Initialized {
|
if let GLContext::Initialized {
|
||||||
|
@ -474,7 +474,7 @@ impl PaintableSink {
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
let mut tmp_caps = Self::pad_templates()[0].caps().clone();
|
let mut tmp_caps = Self::pad_templates()[0].caps().clone();
|
||||||
|
|
||||||
#[cfg(any(target_os = "macos", feature = "gst_gl"))]
|
#[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))]
|
||||||
{
|
{
|
||||||
// Filter out GL caps from the template pads if we have no context
|
// Filter out GL caps from the template pads if we have no context
|
||||||
if !matches!(&*GL_CONTEXT.lock().unwrap(), GLContext::Initialized { .. }) {
|
if !matches!(&*GL_CONTEXT.lock().unwrap(), GLContext::Initialized { .. }) {
|
||||||
|
@ -493,7 +493,7 @@ impl PaintableSink {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_paintable(&self, paintable_storage: &mut MutexGuard<Option<ThreadGuard<Paintable>>>) {
|
fn create_paintable(&self, paintable_storage: &mut MutexGuard<Option<ThreadGuard<Paintable>>>) {
|
||||||
#[cfg(any(target_os = "macos", feature = "gst_gl"))]
|
#[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))]
|
||||||
{
|
{
|
||||||
self.initialize_gl_context();
|
self.initialize_gl_context();
|
||||||
}
|
}
|
||||||
|
@ -523,7 +523,7 @@ impl PaintableSink {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(any(target_os = "macos", feature = "gst_gl"))]
|
#[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))]
|
||||||
{
|
{
|
||||||
let gdk_context = if let GLContext::Initialized { gdk_context, .. } =
|
let gdk_context = if let GLContext::Initialized { gdk_context, .. } =
|
||||||
&*GL_CONTEXT.lock().unwrap()
|
&*GL_CONTEXT.lock().unwrap()
|
||||||
|
@ -534,7 +534,7 @@ impl PaintableSink {
|
||||||
};
|
};
|
||||||
ThreadGuard::new(Paintable::new(gdk_context))
|
ThreadGuard::new(Paintable::new(gdk_context))
|
||||||
}
|
}
|
||||||
#[cfg(not(any(target_os = "macos", feature = "gst_gl")))]
|
#[cfg(not(any(target_os = "macos", target_os = "windows", feature = "gst_gl")))]
|
||||||
{
|
{
|
||||||
ThreadGuard::new(Paintable::new(None))
|
ThreadGuard::new(Paintable::new(None))
|
||||||
}
|
}
|
||||||
|
@ -545,7 +545,7 @@ impl PaintableSink {
|
||||||
*self.sender.lock().unwrap() = Some(sender);
|
*self.sender.lock().unwrap() = Some(sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(target_os = "macos", feature = "gst_gl"))]
|
#[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))]
|
||||||
fn initialize_gl_context(&self) {
|
fn initialize_gl_context(&self) {
|
||||||
gst::debug!(CAT, imp: self, "Realizing GDK GL Context");
|
gst::debug!(CAT, imp: self, "Realizing GDK GL Context");
|
||||||
|
|
||||||
|
@ -555,7 +555,7 @@ impl PaintableSink {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(target_os = "macos", feature = "gst_gl"))]
|
#[cfg(any(target_os = "macos", target_os = "windows", feature = "gst_gl"))]
|
||||||
fn initialize_gl_context_main(&self) {
|
fn initialize_gl_context_main(&self) {
|
||||||
gst::debug!(CAT, imp: self, "Realizing GDK GL Context from main thread");
|
gst::debug!(CAT, imp: self, "Realizing GDK GL Context from main thread");
|
||||||
|
|
||||||
|
@ -603,6 +603,10 @@ impl PaintableSink {
|
||||||
"GdkWaylandGLContext" => (),
|
"GdkWaylandGLContext" => (),
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
"GdkMacosGLContext" => (),
|
"GdkMacosGLContext" => (),
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
"GdkWin32GLContext" => (),
|
||||||
|
#[cfg(all(windows, feature = "winegl"))]
|
||||||
|
"GdkWin32GLContextEGL" => (),
|
||||||
display => {
|
display => {
|
||||||
gst::error!(CAT, imp: self, "Unsupported GDK display {display} for GL");
|
gst::error!(CAT, imp: self, "Unsupported GDK display {display} for GL");
|
||||||
return;
|
return;
|
||||||
|
@ -618,6 +622,7 @@ impl PaintableSink {
|
||||||
|
|
||||||
gst::info!(CAT, imp: self, "Successfully realized GDK GL Context");
|
gst::info!(CAT, imp: self, "Successfully realized GDK GL Context");
|
||||||
|
|
||||||
|
handle_wgl_makecurrent(&ctx);
|
||||||
gdk_context.make_current();
|
gdk_context.make_current();
|
||||||
|
|
||||||
let res = match gdk_context.type_().name() {
|
let res = match gdk_context.type_().name() {
|
||||||
|
@ -629,6 +634,14 @@ impl PaintableSink {
|
||||||
"GdkWaylandGLContext" => self.initialize_waylandegl(gdk_display),
|
"GdkWaylandGLContext" => self.initialize_waylandegl(gdk_display),
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
"GdkMacosGLContext" => self.initialize_macosgl(gdk_display),
|
"GdkMacosGLContext" => self.initialize_macosgl(gdk_display),
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
"GdkWin32GLContext" => {
|
||||||
|
self.initialize_wgl(gdk_display, &gdk_ctx);
|
||||||
|
}
|
||||||
|
#[cfg(all(target_os = "windows", feature = "winegl"))]
|
||||||
|
"GdkWin32GLContextEGL" => {
|
||||||
|
self.initialize_winegl(gdk_display);
|
||||||
|
}
|
||||||
display_type => {
|
display_type => {
|
||||||
unreachable!("Unsupported GDK display {display_type} for GL");
|
unreachable!("Unsupported GDK display {display_type} for GL");
|
||||||
}
|
}
|
||||||
|
@ -666,6 +679,11 @@ impl PaintableSink {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Is this all necessary?
|
||||||
|
deactivate_gdk_wgl_context(&ctx);
|
||||||
|
handle_wgl_makecurrent(&ctx);
|
||||||
|
reactivate_gdk_wgl_context(&ctx);
|
||||||
|
|
||||||
gst::info!(CAT, imp: self, "Successfully initialized GL Context");
|
gst::info!(CAT, imp: self, "Successfully initialized GL Context");
|
||||||
|
|
||||||
*gl_context_guard = GLContext::Initialized {
|
*gl_context_guard = GLContext::Initialized {
|
||||||
|
@ -864,4 +882,165 @@ impl PaintableSink {
|
||||||
Some((gst_display, wrapped_context))
|
Some((gst_display, wrapped_context))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
fn initialize_wgl(
|
||||||
|
&self,
|
||||||
|
display: gdk::Display,
|
||||||
|
context: &gdk::GLContext,
|
||||||
|
) -> Option<(gst_gl::GLDisplay, gst_gl::GLContext)> {
|
||||||
|
gst::info!(
|
||||||
|
CAT,
|
||||||
|
imp: self,
|
||||||
|
"Initializing GL with for Windows WGL backend and display."
|
||||||
|
);
|
||||||
|
|
||||||
|
let platform = gst_gl::GLPlatform::WGL;
|
||||||
|
|
||||||
|
let gl_api = if context.is_legacy() {
|
||||||
|
gst_gl::GLAPI::OPENGL
|
||||||
|
} else {
|
||||||
|
gst_gl::GLAPI::OPENGL3
|
||||||
|
};
|
||||||
|
let gl_ctx = gst_gl::GLContext::current_gl_context(platform);
|
||||||
|
|
||||||
|
if gl_ctx == 0 {
|
||||||
|
gst::error!(CAT, imp: self, "Failed to get handle from GdkGLContext",);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let gst_gl_display = gst_gl::Display::with_type(gst_gl::DisplayType::WIN32);
|
||||||
|
if gst_gl_display.is_none() {
|
||||||
|
gst::error!(CAT, imp: self, "Failed to get GL display");
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_gl_display.filter_gl_api(gl_api);
|
||||||
|
|
||||||
|
let wrapped_context =
|
||||||
|
gst_gl::GLContext::new_wrapped(&gst_gl_display, gl_ctx, platform, gl_api);
|
||||||
|
let wrapped_context = match wrapped_context {
|
||||||
|
None => {
|
||||||
|
gst::error!(CAT, imp: self, "Failed to create wrapped GL context");
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(wrapped_context) => wrapped_context,
|
||||||
|
};
|
||||||
|
|
||||||
|
Some((gst_gl_display, wrapped_context))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(target_os = "windows", feature = "winegl"))]
|
||||||
|
fn initialize_winegl(
|
||||||
|
&self,
|
||||||
|
display: gdk::Display,
|
||||||
|
) -> Option<(gst_gl::GLDisplay, gst_gl::GLContext)> {
|
||||||
|
gst::info!(
|
||||||
|
CAT,
|
||||||
|
imp: self,
|
||||||
|
"Initializing GL with for Windows EGL backend and display."
|
||||||
|
);
|
||||||
|
|
||||||
|
let platform = gst_gl::GLPlatform::EGL;
|
||||||
|
|
||||||
|
let (gl_api, _, _) = gst_gl::GLContext::current_gl_api(platform);
|
||||||
|
let gl_ctx = gst_gl::GLContext::current_gl_context(platform);
|
||||||
|
|
||||||
|
if gl_ctx == 0 {
|
||||||
|
gst::error!(CAT, imp: self, "Failed to get handle from GdkGLContext",);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: bindings
|
||||||
|
unsafe {
|
||||||
|
use gdk_win32::prelude::*;
|
||||||
|
|
||||||
|
let d = display.downcast::<gdk_win32::Win32Display>().unwrap();
|
||||||
|
let egl_display = display.egl_display().unwrap().as_ptr();
|
||||||
|
|
||||||
|
let gst_gl_display =
|
||||||
|
gst_gl_egl::ffi::gst_gl_display_egl_new_with_egl_display(egl_display);
|
||||||
|
if gst_gl_display.is_null() {
|
||||||
|
gst::error!(CAT, imp: self, "Failed to get EGL display");
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let gst_gl_display: gst_gl::GLDisplay =
|
||||||
|
from_glib_full(gst_gl_display as *mut gst_gl::ffi::GstGLDisplay);
|
||||||
|
|
||||||
|
gst_gl_display.filter_gl_api(gl_api);
|
||||||
|
|
||||||
|
let wrapped_context =
|
||||||
|
gst_gl::GLContext::new_wrapped(&gst_gl_display, gl_ctx, platform, gl_api);
|
||||||
|
|
||||||
|
let wrapped_context = match wrapped_context {
|
||||||
|
None => {
|
||||||
|
gst::error!(CAT, imp: self, "Failed to create wrapped GL context");
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(wrapped_context) => wrapped_context,
|
||||||
|
};
|
||||||
|
|
||||||
|
Some((gst_gl_display, wrapped_context))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Workaround for Windows specific GL context problems
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
fn handle_wgl_makecurrent(ctx: &gdk::GLContext) {
|
||||||
|
if ctx.type_().name() != "GdkWin32GLContext" {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
fn epoxy_handle_external_wglMakeCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
epoxy_handle_external_wglMakeCurrent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
fn deactivate_gdk_wgl_context(ctx: &gdk::GLContext) {
|
||||||
|
if ctx.type_().name() != "GdkWin32GLContext" {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
use gdk_win32::prelude::*;
|
||||||
|
|
||||||
|
let surface = context
|
||||||
|
.surface()
|
||||||
|
.unwrap()
|
||||||
|
.downcast::<gdk_win32::Win32Surface>()
|
||||||
|
.unwrap();
|
||||||
|
let hwnd = surface.handle();
|
||||||
|
let hdc = windows_sys::Win32::Graphics::Gdi::GetDC(hwnd);
|
||||||
|
windows_sys::Win32::Graphics::OpenGL::wglMakeCurrent(hdc, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
fn reactivate_gdk_wgl_context(ctx: &gdk::GLContext) {
|
||||||
|
if ctx.type_().name() != "GdkWin32GLContext" {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
context.make_current();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "macos", feature = "gst_gl"))]
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
fn handle_wgl_makecurrent(_ctx: &gdk::GLContext) {}
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "macos", feature = "gst_gl"))]
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
fn deactivate_gdk_wgl_context(_ctx: &gdk::GLContext) {}
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "macos", feature = "gst_gl"))]
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
fn reactivate_gdk_wgl_context(_ctx: &gdk::GLContext) {}
|
||||||
|
|
Loading…
Reference in a new issue