diff --git a/gstreamer-gl/src/auto/gl_display_egl.rs b/gstreamer-gl/egl/src/auto/gl_display_egl.rs similarity index 72% rename from gstreamer-gl/src/auto/gl_display_egl.rs rename to gstreamer-gl/egl/src/auto/gl_display_egl.rs index 85e988ef6..2e2eb1d75 100644 --- a/gstreamer-gl/src/auto/gl_display_egl.rs +++ b/gstreamer-gl/egl/src/auto/gl_display_egl.rs @@ -2,12 +2,11 @@ // from gir-files (https://github.com/gtk-rs/gir-files) // DO NOT EDIT -use crate::GLDisplay; use glib::object::IsA; use glib::translate::*; glib::glib_wrapper! { - pub struct GLDisplayEGL(Object) @extends GLDisplay, gst::Object; + pub struct GLDisplayEGL(Object) @extends gst_gl::GLDisplay, gst::Object; match fn { get_type => || ffi::gst_gl_display_egl_get_type(), @@ -24,8 +23,8 @@ impl GLDisplayEGL { // unsafe { TODO: call ffi:gst_gl_display_egl_new_with_egl_display() } //} - pub fn from_gl_display>(display: &P) -> Option { - skip_assert_initialized!(); + pub fn from_gl_display>(display: &P) -> Option { + assert_initialized_main_thread!(); unsafe { from_glib_full(ffi::gst_gl_display_egl_from_gl_display( display.as_ref().to_glib_none().0, @@ -33,7 +32,7 @@ impl GLDisplayEGL { } } - //pub fn get_from_native(type_: GLDisplayType, display: /*Unimplemented*/Fundamental: UIntPtr) -> /*Unimplemented*/Option { + //pub fn get_from_native(type_: /*Ignored*/gst_gl::GLDisplayType, display: /*Unimplemented*/Fundamental: UIntPtr) -> /*Unimplemented*/Option { // unsafe { TODO: call ffi:gst_gl_display_egl_get_from_native() } //} } @@ -46,3 +45,5 @@ impl Default for GLDisplayEGL { unsafe impl Send for GLDisplayEGL {} unsafe impl Sync for GLDisplayEGL {} + +pub const NONE_GL_DISPLAY_EGL: Option<&GLDisplayEGL> = None; diff --git a/gstreamer-gl/egl/src/auto/mod.rs b/gstreamer-gl/egl/src/auto/mod.rs new file mode 100644 index 000000000..f7f03b1ab --- /dev/null +++ b/gstreamer-gl/egl/src/auto/mod.rs @@ -0,0 +1,9 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir) +// from gir-files (https://github.com/gtk-rs/gir-files) +// DO NOT EDIT + +mod gl_display_egl; +pub use self::gl_display_egl::{GLDisplayEGL, NONE_GL_DISPLAY_EGL}; + +#[doc(hidden)] +pub mod traits {} diff --git a/gstreamer-gl/egl/src/auto/versions.txt b/gstreamer-gl/egl/src/auto/versions.txt new file mode 100644 index 000000000..325fe7cef --- /dev/null +++ b/gstreamer-gl/egl/src/auto/versions.txt @@ -0,0 +1,2 @@ +Generated by gir (https://github.com/gtk-rs/gir @ e941700) +from gir-files (https://github.com/gtk-rs/gir-files @ d2591d00) diff --git a/gstreamer-gl/egl/sys/Cargo.toml b/gstreamer-gl/egl/sys/Cargo.toml new file mode 100644 index 000000000..aa306b27b --- /dev/null +++ b/gstreamer-gl/egl/sys/Cargo.toml @@ -0,0 +1,41 @@ +[package] +name = "gst-glegl-sys" +version = "0.0.1" +links = "\"gstgl-1.0\"" +edition = "2018" +build = "build.rs" +[package.metadata.system-deps.gstreamer_gl_egl_1_0] +name = "gstreamer-gl-egl-1.0" +version = "1.14" + +[package.metadata.system-deps.gstreamer_gl_egl_1_0.v1_16] +version = "1.16" + +[package.metadata.system-deps.gstreamer_gl_egl_1_0.v1_18] +version = "1.18" +[package.metadata.docs.rs] +features = ["dox"] + +[lib] +name = "gst_glegl_sys" + +[dependencies] +libc = "0.2" + +[dependencies.glib-sys] +git = "https://github.com/gtk-rs/sys" + +[dependencies.gstreamer-gl-sys] +git = "https://github.com/gtk-rs/sys" + +[build-dependencies] +system-deps = "2.0" + +[dev-dependencies] +shell-words = "1.0.0" +tempfile = "3" + +[features] +dox = [] +v1_16 = [] +v1_18 = ["v1_16"] diff --git a/gstreamer-gl/egl/sys/build.rs b/gstreamer-gl/egl/sys/build.rs new file mode 100644 index 000000000..13a010cb8 --- /dev/null +++ b/gstreamer-gl/egl/sys/build.rs @@ -0,0 +1,17 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir @ e941700) +// from gir-files (https://github.com/gtk-rs/gir-files @ d2591d00) +// DO NOT EDIT + +#[cfg(not(feature = "dox"))] +use std::process; + +#[cfg(feature = "dox")] +fn main() {} // prevent linking libraries to avoid documentation failure + +#[cfg(not(feature = "dox"))] +fn main() { + if let Err(s) = system_deps::Config::new().probe() { + let _ = eprintln!("{}", s); + process::exit(1); + } +} diff --git a/gstreamer-gl/egl/sys/src/lib.rs b/gstreamer-gl/egl/sys/src/lib.rs new file mode 100644 index 000000000..cccfc8f3d --- /dev/null +++ b/gstreamer-gl/egl/sys/src/lib.rs @@ -0,0 +1,81 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir @ e941700) +// from gir-files (https://github.com/gtk-rs/gir-files @ d2591d00) +// DO NOT EDIT + +#![allow(non_camel_case_types, non_upper_case_globals, non_snake_case)] +#![allow( + clippy::approx_constant, + clippy::type_complexity, + clippy::unreadable_literal +)] +#![cfg_attr(feature = "dox", feature(doc_cfg))] + +use glib_sys as glib; +use gstreamer_gl_sys as gst_gl; + +#[allow(unused_imports)] +use libc::{ + c_char, c_double, c_float, c_int, c_long, c_short, c_uchar, c_uint, c_ulong, c_ushort, c_void, + intptr_t, size_t, ssize_t, time_t, uintptr_t, FILE, +}; + +#[allow(unused_imports)] +use glib::{gboolean, gconstpointer, gpointer, GType}; + +// Constants +pub const GST_GL_DISPLAY_EGL_NAME: *const c_char = + b"gst.gl.display.egl\0" as *const u8 as *const c_char; + +// Records +#[repr(C)] +#[derive(Copy, Clone)] +pub struct GstGLDisplayEGLClass { + pub object_class: gst_gl::GstGLDisplayClass, + pub _padding: [gpointer; 4], +} + +impl ::std::fmt::Debug for GstGLDisplayEGLClass { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + f.debug_struct(&format!("GstGLDisplayEGLClass @ {:?}", self as *const _)) + .field("object_class", &self.object_class) + .field("_padding", &self._padding) + .finish() + } +} + +// Classes +#[repr(C)] +#[derive(Copy, Clone)] +pub struct GstGLDisplayEGL { + pub parent: gst_gl::GstGLDisplay, + pub display: gpointer, + pub foreign_display: gboolean, + pub _padding: [gpointer; 4], +} + +impl ::std::fmt::Debug for GstGLDisplayEGL { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + f.debug_struct(&format!("GstGLDisplayEGL @ {:?}", self as *const _)) + .field("parent", &self.parent) + .finish() + } +} + +#[link(name = "gstgl-1.0")] +extern "C" { + + //========================================================================= + // GstGLDisplayEGL + //========================================================================= + pub fn gst_gl_display_egl_get_type() -> GType; + pub fn gst_gl_display_egl_new() -> *mut GstGLDisplayEGL; + pub fn gst_gl_display_egl_new_with_egl_display(display: gpointer) -> *mut GstGLDisplayEGL; + pub fn gst_gl_display_egl_from_gl_display( + display: *mut gst_gl::GstGLDisplay, + ) -> *mut GstGLDisplayEGL; + pub fn gst_gl_display_egl_get_from_native( + type_: gst_gl::GstGLDisplayType, + display: uintptr_t, + ) -> gpointer; + +} diff --git a/gstreamer-gl/egl/sys/tests/abi.rs b/gstreamer-gl/egl/sys/tests/abi.rs new file mode 100644 index 000000000..54ebaf427 --- /dev/null +++ b/gstreamer-gl/egl/sys/tests/abi.rs @@ -0,0 +1,268 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir @ e941700) +// from gir-files (https://github.com/gtk-rs/gir-files @ d2591d00) +// DO NOT EDIT + +use gst_glegl_sys::*; +use std::env; +use std::error::Error; +use std::mem::{align_of, size_of}; +use std::path::Path; +use std::process::Command; +use std::str; +use tempfile::Builder; + +static PACKAGES: &[&str] = &["gstreamer-gl-egl-1.0"]; + +#[derive(Clone, Debug)] +struct Compiler { + pub args: Vec, +} + +impl Compiler { + pub fn new() -> Result> { + let mut args = get_var("CC", "cc")?; + args.push("-Wno-deprecated-declarations".to_owned()); + // For %z support in printf when using MinGW. + args.push("-D__USE_MINGW_ANSI_STDIO".to_owned()); + args.extend(get_var("CFLAGS", "")?); + args.extend(get_var("CPPFLAGS", "")?); + args.extend(pkg_config_cflags(PACKAGES)?); + Ok(Compiler { args }) + } + + pub fn define<'a, V: Into>>(&mut self, var: &str, val: V) { + let arg = match val.into() { + None => format!("-D{}", var), + Some(val) => format!("-D{}={}", var, val), + }; + self.args.push(arg); + } + + pub fn compile(&self, src: &Path, out: &Path) -> Result<(), Box> { + let mut cmd = self.to_command(); + cmd.arg(src); + cmd.arg("-o"); + cmd.arg(out); + let status = cmd.spawn()?.wait()?; + if !status.success() { + return Err(format!("compilation command {:?} failed, {}", &cmd, status).into()); + } + Ok(()) + } + + fn to_command(&self) -> Command { + let mut cmd = Command::new(&self.args[0]); + cmd.args(&self.args[1..]); + cmd + } +} + +fn get_var(name: &str, default: &str) -> Result, Box> { + match env::var(name) { + Ok(value) => Ok(shell_words::split(&value)?), + Err(env::VarError::NotPresent) => Ok(shell_words::split(default)?), + Err(err) => Err(format!("{} {}", name, err).into()), + } +} + +fn pkg_config_cflags(packages: &[&str]) -> Result, Box> { + if packages.is_empty() { + return Ok(Vec::new()); + } + let mut cmd = Command::new("pkg-config"); + cmd.arg("--cflags"); + cmd.args(packages); + let out = cmd.output()?; + if !out.status.success() { + return Err(format!("command {:?} returned {}", &cmd, out.status).into()); + } + let stdout = str::from_utf8(&out.stdout)?; + Ok(shell_words::split(stdout.trim())?) +} + +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +struct Layout { + size: usize, + alignment: usize, +} + +#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] +struct Results { + /// Number of successfully completed tests. + passed: usize, + /// Total number of failed tests (including those that failed to compile). + failed: usize, + /// Number of tests that failed to compile. + failed_to_compile: usize, +} + +impl Results { + fn record_passed(&mut self) { + self.passed += 1; + } + fn record_failed(&mut self) { + self.failed += 1; + } + fn record_failed_to_compile(&mut self) { + self.failed += 1; + self.failed_to_compile += 1; + } + fn summary(&self) -> String { + format!( + "{} passed; {} failed (compilation errors: {})", + self.passed, self.failed, self.failed_to_compile + ) + } + fn expect_total_success(&self) { + if self.failed == 0 { + println!("OK: {}", self.summary()); + } else { + panic!("FAILED: {}", self.summary()); + }; + } +} + +#[test] +fn cross_validate_constants_with_c() { + let tmpdir = Builder::new() + .prefix("abi") + .tempdir() + .expect("temporary directory"); + let cc = Compiler::new().expect("configured compiler"); + + assert_eq!( + "1", + get_c_value(tmpdir.path(), &cc, "1").expect("C constant"), + "failed to obtain correct constant value for 1" + ); + + let mut results: Results = Default::default(); + for (i, &(name, rust_value)) in RUST_CONSTANTS.iter().enumerate() { + match get_c_value(tmpdir.path(), &cc, name) { + Err(e) => { + results.record_failed_to_compile(); + eprintln!("{}", e); + } + Ok(ref c_value) => { + if rust_value == c_value { + results.record_passed(); + } else { + results.record_failed(); + eprintln!( + "Constant value mismatch for {}\nRust: {:?}\nC: {:?}", + name, rust_value, c_value + ); + } + } + }; + if (i + 1) % 25 == 0 { + println!("constants ... {}", results.summary()); + } + } + results.expect_total_success(); +} + +#[test] +fn cross_validate_layout_with_c() { + let tmpdir = Builder::new() + .prefix("abi") + .tempdir() + .expect("temporary directory"); + let cc = Compiler::new().expect("configured compiler"); + + assert_eq!( + Layout { + size: 1, + alignment: 1 + }, + get_c_layout(tmpdir.path(), &cc, "char").expect("C layout"), + "failed to obtain correct layout for char type" + ); + + let mut results: Results = Default::default(); + for (i, &(name, rust_layout)) in RUST_LAYOUTS.iter().enumerate() { + match get_c_layout(tmpdir.path(), &cc, name) { + Err(e) => { + results.record_failed_to_compile(); + eprintln!("{}", e); + } + Ok(c_layout) => { + if rust_layout == c_layout { + results.record_passed(); + } else { + results.record_failed(); + eprintln!( + "Layout mismatch for {}\nRust: {:?}\nC: {:?}", + name, rust_layout, &c_layout + ); + } + } + }; + if (i + 1) % 25 == 0 { + println!("layout ... {}", results.summary()); + } + } + results.expect_total_success(); +} + +fn get_c_layout(dir: &Path, cc: &Compiler, name: &str) -> Result> { + let exe = dir.join("layout"); + let mut cc = cc.clone(); + cc.define("ABI_TYPE_NAME", name); + cc.compile(Path::new("tests/layout.c"), &exe)?; + + let mut abi_cmd = Command::new(exe); + let output = abi_cmd.output()?; + if !output.status.success() { + return Err(format!("command {:?} failed, {:?}", &abi_cmd, &output).into()); + } + + let stdout = str::from_utf8(&output.stdout)?; + let mut words = stdout.trim().split_whitespace(); + let size = words.next().unwrap().parse().unwrap(); + let alignment = words.next().unwrap().parse().unwrap(); + Ok(Layout { size, alignment }) +} + +fn get_c_value(dir: &Path, cc: &Compiler, name: &str) -> Result> { + let exe = dir.join("constant"); + let mut cc = cc.clone(); + cc.define("ABI_CONSTANT_NAME", name); + cc.compile(Path::new("tests/constant.c"), &exe)?; + + let mut abi_cmd = Command::new(exe); + let output = abi_cmd.output()?; + if !output.status.success() { + return Err(format!("command {:?} failed, {:?}", &abi_cmd, &output).into()); + } + + let output = str::from_utf8(&output.stdout)?.trim(); + if !output.starts_with("###gir test###") || !output.ends_with("###gir test###") { + return Err(format!( + "command {:?} return invalid output, {:?}", + &abi_cmd, &output + ) + .into()); + } + + Ok(String::from(&output[14..(output.len() - 14)])) +} + +const RUST_LAYOUTS: &[(&str, Layout)] = &[ + ( + "GstGLDisplayEGL", + Layout { + size: size_of::(), + alignment: align_of::(), + }, + ), + ( + "GstGLDisplayEGLClass", + Layout { + size: size_of::(), + alignment: align_of::(), + }, + ), +]; + +const RUST_CONSTANTS: &[(&str, &str)] = &[("GST_GL_DISPLAY_EGL_NAME", "gst.gl.display.egl")]; diff --git a/gstreamer-gl/egl/sys/tests/constant.c b/gstreamer-gl/egl/sys/tests/constant.c new file mode 100644 index 000000000..6cd272ba1 --- /dev/null +++ b/gstreamer-gl/egl/sys/tests/constant.c @@ -0,0 +1,27 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir @ e941700) +// from gir-files (https://github.com/gtk-rs/gir-files @ d2591d00) +// DO NOT EDIT + +#include "manual.h" +#include + +int main() { + printf(_Generic((ABI_CONSTANT_NAME), + char *: "###gir test###%s###gir test###\n", + const char *: "###gir test###%s###gir test###\n", + char: "###gir test###%c###gir test###\n", + signed char: "###gir test###%hhd###gir test###\n", + unsigned char: "###gir test###%hhu###gir test###\n", + short int: "###gir test###%hd###gir test###\n", + unsigned short int: "###gir test###%hu###gir test###\n", + int: "###gir test###%d###gir test###\n", + unsigned int: "###gir test###%u###gir test###\n", + long: "###gir test###%ld###gir test###\n", + unsigned long: "###gir test###%lu###gir test###\n", + long long: "###gir test###%lld###gir test###\n", + unsigned long long: "###gir test###%llu###gir test###\n", + double: "###gir test###%f###gir test###\n", + long double: "###gir test###%ld###gir test###\n"), + ABI_CONSTANT_NAME); + return 0; +} diff --git a/gstreamer-gl/egl/sys/tests/layout.c b/gstreamer-gl/egl/sys/tests/layout.c new file mode 100644 index 000000000..166185041 --- /dev/null +++ b/gstreamer-gl/egl/sys/tests/layout.c @@ -0,0 +1,12 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir @ e941700) +// from gir-files (https://github.com/gtk-rs/gir-files @ d2591d00) +// DO NOT EDIT + +#include "manual.h" +#include +#include + +int main() { + printf("%zu\n%zu", sizeof(ABI_TYPE_NAME), alignof(ABI_TYPE_NAME)); + return 0; +} diff --git a/gstreamer-gl/egl/sys/tests/manual.h b/gstreamer-gl/egl/sys/tests/manual.h new file mode 100644 index 000000000..ab11065e0 --- /dev/null +++ b/gstreamer-gl/egl/sys/tests/manual.h @@ -0,0 +1,3 @@ +// Feel free to edit this file, it won't be regenerated by gir generator unless removed. + +#include diff --git a/gstreamer-gl/src/auto/mod.rs b/gstreamer-gl/src/auto/mod.rs index e878369ea..2203a225a 100644 --- a/gstreamer-gl/src/auto/mod.rs +++ b/gstreamer-gl/src/auto/mod.rs @@ -23,27 +23,6 @@ mod gl_display; pub use self::gl_display::GLDisplayExt; pub use self::gl_display::{GLDisplay, NONE_GL_DISPLAY}; -#[cfg(any(feature = "egl", feature = "dox"))] -#[cfg_attr(feature = "dox", doc(cfg(feature = "egl")))] -mod gl_display_egl; -#[cfg(any(feature = "egl", feature = "dox"))] -#[cfg_attr(feature = "dox", doc(cfg(feature = "egl")))] -pub use self::gl_display_egl::GLDisplayEGL; - -#[cfg(any(feature = "wayland", feature = "dox"))] -#[cfg_attr(feature = "dox", doc(cfg(feature = "wayland")))] -mod gl_display_wayland; -#[cfg(any(feature = "wayland", feature = "dox"))] -#[cfg_attr(feature = "dox", doc(cfg(feature = "wayland")))] -pub use self::gl_display_wayland::GLDisplayWayland; - -#[cfg(any(feature = "x11", feature = "dox"))] -#[cfg_attr(feature = "dox", doc(cfg(feature = "x11")))] -mod gl_display_x11; -#[cfg(any(feature = "x11", feature = "dox"))] -#[cfg_attr(feature = "dox", doc(cfg(feature = "x11")))] -pub use self::gl_display_x11::GLDisplayX11; - mod gl_framebuffer; pub use self::gl_framebuffer::GLFramebufferExt; pub use self::gl_framebuffer::{GLFramebuffer, NONE_GL_FRAMEBUFFER}; diff --git a/gstreamer-gl/sys/src/lib.rs b/gstreamer-gl/sys/src/lib.rs index 9141aa493..0df83d27e 100644 --- a/gstreamer-gl/sys/src/lib.rs +++ b/gstreamer-gl/sys/src/lib.rs @@ -599,74 +599,11 @@ impl ::std::fmt::Debug for GstGLDisplayClass { } } -#[cfg(any(feature = "egl", feature = "dox"))] -#[cfg_attr(feature = "dox", doc(cfg(feature = "egl")))] -#[repr(C)] -#[derive(Copy, Clone)] -pub struct GstGLDisplayEGLClass { - pub object_class: GstGLDisplayClass, - pub _padding: [gpointer; 4], -} - -#[cfg(any(feature = "egl", feature = "dox"))] -#[cfg_attr(feature = "dox", doc(cfg(feature = "egl")))] -impl ::std::fmt::Debug for GstGLDisplayEGLClass { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - f.debug_struct(&format!("GstGLDisplayEGLClass @ {:?}", self as *const _)) - .field("object_class", &self.object_class) - .field("_padding", &self._padding) - .finish() - } -} - #[repr(C)] pub struct _GstGLDisplayPrivate(c_void); pub type GstGLDisplayPrivate = *mut _GstGLDisplayPrivate; -#[cfg(any(feature = "wayland", feature = "dox"))] -#[cfg_attr(feature = "dox", doc(cfg(feature = "wayland")))] -#[repr(C)] -#[derive(Copy, Clone)] -pub struct GstGLDisplayWaylandClass { - pub object_class: GstGLDisplayClass, - pub _padding: [gpointer; 4], -} - -#[cfg(any(feature = "wayland", feature = "dox"))] -#[cfg_attr(feature = "dox", doc(cfg(feature = "wayland")))] -impl ::std::fmt::Debug for GstGLDisplayWaylandClass { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - f.debug_struct(&format!( - "GstGLDisplayWaylandClass @ {:?}", - self as *const _ - )) - .field("object_class", &self.object_class) - .field("_padding", &self._padding) - .finish() - } -} - -#[cfg(any(feature = "x11", feature = "dox"))] -#[cfg_attr(feature = "dox", doc(cfg(feature = "x11")))] -#[repr(C)] -#[derive(Copy, Clone)] -pub struct GstGLDisplayX11Class { - pub object_class: GstGLDisplayClass, - pub _padding: [gpointer; 4], -} - -#[cfg(any(feature = "x11", feature = "dox"))] -#[cfg_attr(feature = "dox", doc(cfg(feature = "x11")))] -impl ::std::fmt::Debug for GstGLDisplayX11Class { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - f.debug_struct(&format!("GstGLDisplayX11Class @ {:?}", self as *const _)) - .field("object_class", &self.object_class) - .field("_padding", &self._padding) - .finish() - } -} - #[repr(C)] #[derive(Copy, Clone)] pub struct GstGLFilterClass { @@ -1294,79 +1231,6 @@ impl ::std::fmt::Debug for GstGLDisplay { } } -#[cfg(any(feature = "egl", feature = "dox"))] -#[cfg_attr(feature = "dox", doc(cfg(feature = "egl")))] -#[repr(C)] -#[derive(Copy, Clone)] -pub struct GstGLDisplayEGL { - pub parent: GstGLDisplay, - pub display: gpointer, - pub foreign_display: gboolean, - pub _padding: [gpointer; 4], -} - -#[cfg(any(feature = "egl", feature = "dox"))] -#[cfg_attr(feature = "dox", doc(cfg(feature = "egl")))] -impl ::std::fmt::Debug for GstGLDisplayEGL { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - f.debug_struct(&format!("GstGLDisplayEGL @ {:?}", self as *const _)) - .field("parent", &self.parent) - .finish() - } -} - -#[cfg(any(feature = "wayland", feature = "dox"))] -#[cfg_attr(feature = "dox", doc(cfg(feature = "wayland")))] -#[repr(C)] -#[derive(Copy, Clone)] -pub struct GstGLDisplayWayland { - pub parent: GstGLDisplay, - pub display: gpointer, - pub registry: gpointer, - pub compositor: gpointer, - pub subcompositor: gpointer, - pub shell: gpointer, - pub foreign_display: gboolean, - pub _padding: [gpointer; 4], -} - -#[cfg(any(feature = "wayland", feature = "dox"))] -#[cfg_attr(feature = "dox", doc(cfg(feature = "wayland")))] -impl ::std::fmt::Debug for GstGLDisplayWayland { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - f.debug_struct(&format!("GstGLDisplayWayland @ {:?}", self as *const _)) - .field("parent", &self.parent) - .field("display", &self.display) - .field("registry", &self.registry) - .field("compositor", &self.compositor) - .field("subcompositor", &self.subcompositor) - .field("shell", &self.shell) - .finish() - } -} - -#[cfg(any(feature = "x11", feature = "dox"))] -#[cfg_attr(feature = "dox", doc(cfg(feature = "x11")))] -#[repr(C)] -#[derive(Copy, Clone)] -pub struct GstGLDisplayX11 { - pub parent: GstGLDisplay, - pub name: *mut c_char, - pub display: gpointer, - pub xcb_connection: gpointer, - pub foreign_display: gboolean, - pub _padding: [gpointer; 4], -} - -#[cfg(any(feature = "x11", feature = "dox"))] -#[cfg_attr(feature = "dox", doc(cfg(feature = "x11")))] -impl ::std::fmt::Debug for GstGLDisplayX11 { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - f.debug_struct(&format!("GstGLDisplayX11 @ {:?}", self as *const _)) - .finish() - } -} - #[repr(C)] #[derive(Copy, Clone)] pub struct GstGLFilter { @@ -1872,7 +1736,8 @@ extern "C" { user_data: gpointer, notify: glib::GDestroyNotify, ); - pub fn gst_gl_memory_read_pixels(gl_mem: *mut GstGLMemory, read_pointer: gpointer) -> gboolean; + pub fn gst_gl_memory_read_pixels(gl_mem: *mut GstGLMemory, write_pointer: gpointer) + -> gboolean; pub fn gst_gl_memory_texsubimage(gl_mem: *mut GstGLMemory, read_pointer: gpointer); pub fn gst_gl_memory_init_once(); pub fn gst_gl_memory_setup_buffer( @@ -2260,54 +2125,6 @@ extern "C" { compare_func: glib::GCompareFunc, ) -> *mut GstGLWindow; - //========================================================================= - // GstGLDisplayEGL - //========================================================================= - #[cfg(any(feature = "egl", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "egl")))] - pub fn gst_gl_display_egl_get_type() -> GType; - #[cfg(any(feature = "egl", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "egl")))] - pub fn gst_gl_display_egl_new() -> *mut GstGLDisplayEGL; - #[cfg(any(feature = "egl", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "egl")))] - pub fn gst_gl_display_egl_new_with_egl_display(display: gpointer) -> *mut GstGLDisplayEGL; - #[cfg(any(feature = "egl", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "egl")))] - pub fn gst_gl_display_egl_from_gl_display(display: *mut GstGLDisplay) -> *mut GstGLDisplayEGL; - #[cfg(any(feature = "egl", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "egl")))] - pub fn gst_gl_display_egl_get_from_native( - type_: GstGLDisplayType, - display: uintptr_t, - ) -> gpointer; - - //========================================================================= - // GstGLDisplayWayland - //========================================================================= - #[cfg(any(feature = "wayland", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "wayland")))] - pub fn gst_gl_display_wayland_get_type() -> GType; - #[cfg(any(feature = "wayland", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "wayland")))] - pub fn gst_gl_display_wayland_new(name: *const c_char) -> *mut GstGLDisplayWayland; - #[cfg(any(feature = "wayland", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "wayland")))] - pub fn gst_gl_display_wayland_new_with_display(display: gpointer) -> *mut GstGLDisplayWayland; - - //========================================================================= - // GstGLDisplayX11 - //========================================================================= - #[cfg(any(feature = "x11", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "x11")))] - pub fn gst_gl_display_x11_get_type() -> GType; - #[cfg(any(feature = "x11", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "x11")))] - pub fn gst_gl_display_x11_new(name: *const c_char) -> *mut GstGLDisplayX11; - #[cfg(any(feature = "x11", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "x11")))] - pub fn gst_gl_display_x11_new_with_display(display: gpointer) -> *mut GstGLDisplayX11; - //========================================================================= // GstGLFilter //========================================================================= diff --git a/gstreamer-gl/sys/tests/abi.rs b/gstreamer-gl/sys/tests/abi.rs index b2fdfb3f5..066dd3cd8 100644 --- a/gstreamer-gl/sys/tests/abi.rs +++ b/gstreamer-gl/sys/tests/abi.rs @@ -424,24 +424,6 @@ const RUST_LAYOUTS: &[(&str, Layout)] = &[ alignment: align_of::(), }, ), - #[cfg(any(feature = "egl", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "egl")))] - ( - "GstGLDisplayEGL", - Layout { - size: size_of::(), - alignment: align_of::(), - }, - ), - #[cfg(any(feature = "egl", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "egl")))] - ( - "GstGLDisplayEGLClass", - Layout { - size: size_of::(), - alignment: align_of::(), - }, - ), ( "GstGLDisplayType", Layout { @@ -449,42 +431,6 @@ const RUST_LAYOUTS: &[(&str, Layout)] = &[ alignment: align_of::(), }, ), - #[cfg(any(feature = "wayland", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "wayland")))] - ( - "GstGLDisplayWayland", - Layout { - size: size_of::(), - alignment: align_of::(), - }, - ), - #[cfg(any(feature = "wayland", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "wayland")))] - ( - "GstGLDisplayWaylandClass", - Layout { - size: size_of::(), - alignment: align_of::(), - }, - ), - #[cfg(any(feature = "x11", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "x11")))] - ( - "GstGLDisplayX11", - Layout { - size: size_of::(), - alignment: align_of::(), - }, - ), - #[cfg(any(feature = "x11", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "x11")))] - ( - "GstGLDisplayX11Class", - Layout { - size: size_of::(), - alignment: align_of::(), - }, - ), ( "GstGLFilter", Layout { diff --git a/gstreamer-gl/src/auto/gl_display_wayland.rs b/gstreamer-gl/wayland/src/auto/gl_display_wayland.rs similarity index 85% rename from gstreamer-gl/src/auto/gl_display_wayland.rs rename to gstreamer-gl/wayland/src/auto/gl_display_wayland.rs index 22b13dd11..dfed5c20a 100644 --- a/gstreamer-gl/src/auto/gl_display_wayland.rs +++ b/gstreamer-gl/wayland/src/auto/gl_display_wayland.rs @@ -2,11 +2,10 @@ // from gir-files (https://github.com/gtk-rs/gir-files) // DO NOT EDIT -use crate::GLDisplay; use glib::translate::*; glib::glib_wrapper! { - pub struct GLDisplayWayland(Object) @extends GLDisplay, gst::Object; + pub struct GLDisplayWayland(Object) @extends gst_gl::GLDisplay, gst::Object; match fn { get_type => || ffi::gst_gl_display_wayland_get_type(), @@ -26,3 +25,5 @@ impl GLDisplayWayland { unsafe impl Send for GLDisplayWayland {} unsafe impl Sync for GLDisplayWayland {} + +pub const NONE_GL_DISPLAY_WAYLAND: Option<&GLDisplayWayland> = None; diff --git a/gstreamer-gl/wayland/src/auto/mod.rs b/gstreamer-gl/wayland/src/auto/mod.rs new file mode 100644 index 000000000..e2ff42059 --- /dev/null +++ b/gstreamer-gl/wayland/src/auto/mod.rs @@ -0,0 +1,9 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir) +// from gir-files (https://github.com/gtk-rs/gir-files) +// DO NOT EDIT + +mod gl_display_wayland; +pub use self::gl_display_wayland::{GLDisplayWayland, NONE_GL_DISPLAY_WAYLAND}; + +#[doc(hidden)] +pub mod traits {} diff --git a/gstreamer-gl/wayland/src/auto/versions.txt b/gstreamer-gl/wayland/src/auto/versions.txt new file mode 100644 index 000000000..325fe7cef --- /dev/null +++ b/gstreamer-gl/wayland/src/auto/versions.txt @@ -0,0 +1,2 @@ +Generated by gir (https://github.com/gtk-rs/gir @ e941700) +from gir-files (https://github.com/gtk-rs/gir-files @ d2591d00) diff --git a/gstreamer-gl/wayland/sys/Cargo.toml b/gstreamer-gl/wayland/sys/Cargo.toml new file mode 100644 index 000000000..9ab215c6c --- /dev/null +++ b/gstreamer-gl/wayland/sys/Cargo.toml @@ -0,0 +1,41 @@ +[package] +name = "gst-gl-wayland-sys" +version = "0.0.1" +links = "\"gstgl-1.0\"" +edition = "2018" +build = "build.rs" +[package.metadata.system-deps.gstreamer_gl_wayland_1_0] +name = "gstreamer-gl-wayland-1.0" +version = "1.14" + +[package.metadata.system-deps.gstreamer_gl_wayland_1_0.v1_16] +version = "1.16" + +[package.metadata.system-deps.gstreamer_gl_wayland_1_0.v1_18] +version = "1.18" +[package.metadata.docs.rs] +features = ["dox"] + +[lib] +name = "gst_gl_wayland_sys" + +[dependencies] +libc = "0.2" + +[dependencies.glib-sys] +git = "https://github.com/gtk-rs/sys" + +[dependencies.gstreamer-gl-sys] +git = "https://github.com/gtk-rs/sys" + +[build-dependencies] +system-deps = "2.0" + +[dev-dependencies] +shell-words = "1.0.0" +tempfile = "3" + +[features] +dox = [] +v1_16 = [] +v1_18 = ["v1_16"] diff --git a/gstreamer-gl/wayland/sys/build.rs b/gstreamer-gl/wayland/sys/build.rs new file mode 100644 index 000000000..13a010cb8 --- /dev/null +++ b/gstreamer-gl/wayland/sys/build.rs @@ -0,0 +1,17 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir @ e941700) +// from gir-files (https://github.com/gtk-rs/gir-files @ d2591d00) +// DO NOT EDIT + +#[cfg(not(feature = "dox"))] +use std::process; + +#[cfg(feature = "dox")] +fn main() {} // prevent linking libraries to avoid documentation failure + +#[cfg(not(feature = "dox"))] +fn main() { + if let Err(s) = system_deps::Config::new().probe() { + let _ = eprintln!("{}", s); + process::exit(1); + } +} diff --git a/gstreamer-gl/wayland/sys/src/lib.rs b/gstreamer-gl/wayland/sys/src/lib.rs new file mode 100644 index 000000000..29ef16bc5 --- /dev/null +++ b/gstreamer-gl/wayland/sys/src/lib.rs @@ -0,0 +1,82 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir @ e941700) +// from gir-files (https://github.com/gtk-rs/gir-files @ d2591d00) +// DO NOT EDIT + +#![allow(non_camel_case_types, non_upper_case_globals, non_snake_case)] +#![allow( + clippy::approx_constant, + clippy::type_complexity, + clippy::unreadable_literal +)] +#![cfg_attr(feature = "dox", feature(doc_cfg))] + +use glib_sys as glib; +use gstreamer_gl_sys as gst_gl; + +#[allow(unused_imports)] +use libc::{ + c_char, c_double, c_float, c_int, c_long, c_short, c_uchar, c_uint, c_ulong, c_ushort, c_void, + intptr_t, size_t, ssize_t, time_t, uintptr_t, FILE, +}; + +#[allow(unused_imports)] +use glib::{gboolean, gconstpointer, gpointer, GType}; + +// Records +#[repr(C)] +#[derive(Copy, Clone)] +pub struct GstGLDisplayWaylandClass { + pub object_class: gst_gl::GstGLDisplayClass, + pub _padding: [gpointer; 4], +} + +impl ::std::fmt::Debug for GstGLDisplayWaylandClass { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + f.debug_struct(&format!( + "GstGLDisplayWaylandClass @ {:?}", + self as *const _ + )) + .field("object_class", &self.object_class) + .field("_padding", &self._padding) + .finish() + } +} + +// Classes +#[repr(C)] +#[derive(Copy, Clone)] +pub struct GstGLDisplayWayland { + pub parent: gst_gl::GstGLDisplay, + pub display: gpointer, + pub registry: gpointer, + pub compositor: gpointer, + pub subcompositor: gpointer, + pub shell: gpointer, + pub foreign_display: gboolean, + pub _padding: [gpointer; 4], +} + +impl ::std::fmt::Debug for GstGLDisplayWayland { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + f.debug_struct(&format!("GstGLDisplayWayland @ {:?}", self as *const _)) + .field("parent", &self.parent) + .field("display", &self.display) + .field("registry", &self.registry) + .field("compositor", &self.compositor) + .field("subcompositor", &self.subcompositor) + .field("shell", &self.shell) + .finish() + } +} + +#[link(name = "gstgl-1.0")] +extern "C" { + + //========================================================================= + // GstGLDisplayWayland + //========================================================================= + pub fn gst_gl_display_wayland_get_type() -> GType; + pub fn gst_gl_display_wayland_new(name: *const c_char) -> *mut GstGLDisplayWayland; + pub fn gst_gl_display_wayland_new_with_display(display: gpointer) -> *mut GstGLDisplayWayland; + +} diff --git a/gstreamer-gl/wayland/sys/tests/abi.rs b/gstreamer-gl/wayland/sys/tests/abi.rs new file mode 100644 index 000000000..953943ea3 --- /dev/null +++ b/gstreamer-gl/wayland/sys/tests/abi.rs @@ -0,0 +1,268 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir @ e941700) +// from gir-files (https://github.com/gtk-rs/gir-files @ d2591d00) +// DO NOT EDIT + +use gst_gl_wayland_sys::*; +use std::env; +use std::error::Error; +use std::mem::{align_of, size_of}; +use std::path::Path; +use std::process::Command; +use std::str; +use tempfile::Builder; + +static PACKAGES: &[&str] = &["gstreamer-gl-wayland-1.0"]; + +#[derive(Clone, Debug)] +struct Compiler { + pub args: Vec, +} + +impl Compiler { + pub fn new() -> Result> { + let mut args = get_var("CC", "cc")?; + args.push("-Wno-deprecated-declarations".to_owned()); + // For %z support in printf when using MinGW. + args.push("-D__USE_MINGW_ANSI_STDIO".to_owned()); + args.extend(get_var("CFLAGS", "")?); + args.extend(get_var("CPPFLAGS", "")?); + args.extend(pkg_config_cflags(PACKAGES)?); + Ok(Compiler { args }) + } + + pub fn define<'a, V: Into>>(&mut self, var: &str, val: V) { + let arg = match val.into() { + None => format!("-D{}", var), + Some(val) => format!("-D{}={}", var, val), + }; + self.args.push(arg); + } + + pub fn compile(&self, src: &Path, out: &Path) -> Result<(), Box> { + let mut cmd = self.to_command(); + cmd.arg(src); + cmd.arg("-o"); + cmd.arg(out); + let status = cmd.spawn()?.wait()?; + if !status.success() { + return Err(format!("compilation command {:?} failed, {}", &cmd, status).into()); + } + Ok(()) + } + + fn to_command(&self) -> Command { + let mut cmd = Command::new(&self.args[0]); + cmd.args(&self.args[1..]); + cmd + } +} + +fn get_var(name: &str, default: &str) -> Result, Box> { + match env::var(name) { + Ok(value) => Ok(shell_words::split(&value)?), + Err(env::VarError::NotPresent) => Ok(shell_words::split(default)?), + Err(err) => Err(format!("{} {}", name, err).into()), + } +} + +fn pkg_config_cflags(packages: &[&str]) -> Result, Box> { + if packages.is_empty() { + return Ok(Vec::new()); + } + let mut cmd = Command::new("pkg-config"); + cmd.arg("--cflags"); + cmd.args(packages); + let out = cmd.output()?; + if !out.status.success() { + return Err(format!("command {:?} returned {}", &cmd, out.status).into()); + } + let stdout = str::from_utf8(&out.stdout)?; + Ok(shell_words::split(stdout.trim())?) +} + +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +struct Layout { + size: usize, + alignment: usize, +} + +#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] +struct Results { + /// Number of successfully completed tests. + passed: usize, + /// Total number of failed tests (including those that failed to compile). + failed: usize, + /// Number of tests that failed to compile. + failed_to_compile: usize, +} + +impl Results { + fn record_passed(&mut self) { + self.passed += 1; + } + fn record_failed(&mut self) { + self.failed += 1; + } + fn record_failed_to_compile(&mut self) { + self.failed += 1; + self.failed_to_compile += 1; + } + fn summary(&self) -> String { + format!( + "{} passed; {} failed (compilation errors: {})", + self.passed, self.failed, self.failed_to_compile + ) + } + fn expect_total_success(&self) { + if self.failed == 0 { + println!("OK: {}", self.summary()); + } else { + panic!("FAILED: {}", self.summary()); + }; + } +} + +#[test] +fn cross_validate_constants_with_c() { + let tmpdir = Builder::new() + .prefix("abi") + .tempdir() + .expect("temporary directory"); + let cc = Compiler::new().expect("configured compiler"); + + assert_eq!( + "1", + get_c_value(tmpdir.path(), &cc, "1").expect("C constant"), + "failed to obtain correct constant value for 1" + ); + + let mut results: Results = Default::default(); + for (i, &(name, rust_value)) in RUST_CONSTANTS.iter().enumerate() { + match get_c_value(tmpdir.path(), &cc, name) { + Err(e) => { + results.record_failed_to_compile(); + eprintln!("{}", e); + } + Ok(ref c_value) => { + if rust_value == c_value { + results.record_passed(); + } else { + results.record_failed(); + eprintln!( + "Constant value mismatch for {}\nRust: {:?}\nC: {:?}", + name, rust_value, c_value + ); + } + } + }; + if (i + 1) % 25 == 0 { + println!("constants ... {}", results.summary()); + } + } + results.expect_total_success(); +} + +#[test] +fn cross_validate_layout_with_c() { + let tmpdir = Builder::new() + .prefix("abi") + .tempdir() + .expect("temporary directory"); + let cc = Compiler::new().expect("configured compiler"); + + assert_eq!( + Layout { + size: 1, + alignment: 1 + }, + get_c_layout(tmpdir.path(), &cc, "char").expect("C layout"), + "failed to obtain correct layout for char type" + ); + + let mut results: Results = Default::default(); + for (i, &(name, rust_layout)) in RUST_LAYOUTS.iter().enumerate() { + match get_c_layout(tmpdir.path(), &cc, name) { + Err(e) => { + results.record_failed_to_compile(); + eprintln!("{}", e); + } + Ok(c_layout) => { + if rust_layout == c_layout { + results.record_passed(); + } else { + results.record_failed(); + eprintln!( + "Layout mismatch for {}\nRust: {:?}\nC: {:?}", + name, rust_layout, &c_layout + ); + } + } + }; + if (i + 1) % 25 == 0 { + println!("layout ... {}", results.summary()); + } + } + results.expect_total_success(); +} + +fn get_c_layout(dir: &Path, cc: &Compiler, name: &str) -> Result> { + let exe = dir.join("layout"); + let mut cc = cc.clone(); + cc.define("ABI_TYPE_NAME", name); + cc.compile(Path::new("tests/layout.c"), &exe)?; + + let mut abi_cmd = Command::new(exe); + let output = abi_cmd.output()?; + if !output.status.success() { + return Err(format!("command {:?} failed, {:?}", &abi_cmd, &output).into()); + } + + let stdout = str::from_utf8(&output.stdout)?; + let mut words = stdout.trim().split_whitespace(); + let size = words.next().unwrap().parse().unwrap(); + let alignment = words.next().unwrap().parse().unwrap(); + Ok(Layout { size, alignment }) +} + +fn get_c_value(dir: &Path, cc: &Compiler, name: &str) -> Result> { + let exe = dir.join("constant"); + let mut cc = cc.clone(); + cc.define("ABI_CONSTANT_NAME", name); + cc.compile(Path::new("tests/constant.c"), &exe)?; + + let mut abi_cmd = Command::new(exe); + let output = abi_cmd.output()?; + if !output.status.success() { + return Err(format!("command {:?} failed, {:?}", &abi_cmd, &output).into()); + } + + let output = str::from_utf8(&output.stdout)?.trim(); + if !output.starts_with("###gir test###") || !output.ends_with("###gir test###") { + return Err(format!( + "command {:?} return invalid output, {:?}", + &abi_cmd, &output + ) + .into()); + } + + Ok(String::from(&output[14..(output.len() - 14)])) +} + +const RUST_LAYOUTS: &[(&str, Layout)] = &[ + ( + "GstGLDisplayWayland", + Layout { + size: size_of::(), + alignment: align_of::(), + }, + ), + ( + "GstGLDisplayWaylandClass", + Layout { + size: size_of::(), + alignment: align_of::(), + }, + ), +]; + +const RUST_CONSTANTS: &[(&str, &str)] = &[]; diff --git a/gstreamer-gl/wayland/sys/tests/constant.c b/gstreamer-gl/wayland/sys/tests/constant.c new file mode 100644 index 000000000..6cd272ba1 --- /dev/null +++ b/gstreamer-gl/wayland/sys/tests/constant.c @@ -0,0 +1,27 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir @ e941700) +// from gir-files (https://github.com/gtk-rs/gir-files @ d2591d00) +// DO NOT EDIT + +#include "manual.h" +#include + +int main() { + printf(_Generic((ABI_CONSTANT_NAME), + char *: "###gir test###%s###gir test###\n", + const char *: "###gir test###%s###gir test###\n", + char: "###gir test###%c###gir test###\n", + signed char: "###gir test###%hhd###gir test###\n", + unsigned char: "###gir test###%hhu###gir test###\n", + short int: "###gir test###%hd###gir test###\n", + unsigned short int: "###gir test###%hu###gir test###\n", + int: "###gir test###%d###gir test###\n", + unsigned int: "###gir test###%u###gir test###\n", + long: "###gir test###%ld###gir test###\n", + unsigned long: "###gir test###%lu###gir test###\n", + long long: "###gir test###%lld###gir test###\n", + unsigned long long: "###gir test###%llu###gir test###\n", + double: "###gir test###%f###gir test###\n", + long double: "###gir test###%ld###gir test###\n"), + ABI_CONSTANT_NAME); + return 0; +} diff --git a/gstreamer-gl/wayland/sys/tests/layout.c b/gstreamer-gl/wayland/sys/tests/layout.c new file mode 100644 index 000000000..166185041 --- /dev/null +++ b/gstreamer-gl/wayland/sys/tests/layout.c @@ -0,0 +1,12 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir @ e941700) +// from gir-files (https://github.com/gtk-rs/gir-files @ d2591d00) +// DO NOT EDIT + +#include "manual.h" +#include +#include + +int main() { + printf("%zu\n%zu", sizeof(ABI_TYPE_NAME), alignof(ABI_TYPE_NAME)); + return 0; +} diff --git a/gstreamer-gl/wayland/sys/tests/manual.h b/gstreamer-gl/wayland/sys/tests/manual.h new file mode 100644 index 000000000..bd90ab47c --- /dev/null +++ b/gstreamer-gl/wayland/sys/tests/manual.h @@ -0,0 +1,3 @@ +// Feel free to edit this file, it won't be regenerated by gir generator unless removed. + +#include diff --git a/gstreamer-gl/src/auto/gl_display_x11.rs b/gstreamer-gl/x11/src/auto/gl_display_x11.rs similarity index 86% rename from gstreamer-gl/src/auto/gl_display_x11.rs rename to gstreamer-gl/x11/src/auto/gl_display_x11.rs index 08e9c032b..b2f887d1f 100644 --- a/gstreamer-gl/src/auto/gl_display_x11.rs +++ b/gstreamer-gl/x11/src/auto/gl_display_x11.rs @@ -2,11 +2,10 @@ // from gir-files (https://github.com/gtk-rs/gir-files) // DO NOT EDIT -use crate::GLDisplay; use glib::translate::*; glib::glib_wrapper! { - pub struct GLDisplayX11(Object) @extends GLDisplay, gst::Object; + pub struct GLDisplayX11(Object) @extends gst_gl::GLDisplay, gst::Object; match fn { get_type => || ffi::gst_gl_display_x11_get_type(), @@ -26,3 +25,5 @@ impl GLDisplayX11 { unsafe impl Send for GLDisplayX11 {} unsafe impl Sync for GLDisplayX11 {} + +pub const NONE_GL_DISPLAY_X11: Option<&GLDisplayX11> = None; diff --git a/gstreamer-gl/x11/src/auto/mod.rs b/gstreamer-gl/x11/src/auto/mod.rs new file mode 100644 index 000000000..1857af48d --- /dev/null +++ b/gstreamer-gl/x11/src/auto/mod.rs @@ -0,0 +1,9 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir) +// from gir-files (https://github.com/gtk-rs/gir-files) +// DO NOT EDIT + +mod gl_display_x11; +pub use self::gl_display_x11::{GLDisplayX11, NONE_GL_DISPLAY_X11}; + +#[doc(hidden)] +pub mod traits {} diff --git a/gstreamer-gl/x11/src/auto/versions.txt b/gstreamer-gl/x11/src/auto/versions.txt new file mode 100644 index 000000000..325fe7cef --- /dev/null +++ b/gstreamer-gl/x11/src/auto/versions.txt @@ -0,0 +1,2 @@ +Generated by gir (https://github.com/gtk-rs/gir @ e941700) +from gir-files (https://github.com/gtk-rs/gir-files @ d2591d00) diff --git a/gstreamer-gl/x11/sys/Cargo.toml b/gstreamer-gl/x11/sys/Cargo.toml new file mode 100644 index 000000000..965aea67e --- /dev/null +++ b/gstreamer-gl/x11/sys/Cargo.toml @@ -0,0 +1,41 @@ +[package] +name = "gst-glx11-sys" +version = "0.0.1" +links = "\"gstgl-1.0\"" +edition = "2018" +build = "build.rs" +[package.metadata.system-deps.gstreamer_gl_x11_1_0] +name = "gstreamer-gl-x11-1.0" +version = "1.14" + +[package.metadata.system-deps.gstreamer_gl_x11_1_0.v1_16] +version = "1.16" + +[package.metadata.system-deps.gstreamer_gl_x11_1_0.v1_18] +version = "1.18" +[package.metadata.docs.rs] +features = ["dox"] + +[lib] +name = "gst_glx11_sys" + +[dependencies] +libc = "0.2" + +[dependencies.glib-sys] +git = "https://github.com/gtk-rs/sys" + +[dependencies.gstreamer-gl-sys] +git = "https://github.com/gtk-rs/sys" + +[build-dependencies] +system-deps = "2.0" + +[dev-dependencies] +shell-words = "1.0.0" +tempfile = "3" + +[features] +dox = [] +v1_16 = [] +v1_18 = ["v1_16"] diff --git a/gstreamer-gl/x11/sys/build.rs b/gstreamer-gl/x11/sys/build.rs new file mode 100644 index 000000000..13a010cb8 --- /dev/null +++ b/gstreamer-gl/x11/sys/build.rs @@ -0,0 +1,17 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir @ e941700) +// from gir-files (https://github.com/gtk-rs/gir-files @ d2591d00) +// DO NOT EDIT + +#[cfg(not(feature = "dox"))] +use std::process; + +#[cfg(feature = "dox")] +fn main() {} // prevent linking libraries to avoid documentation failure + +#[cfg(not(feature = "dox"))] +fn main() { + if let Err(s) = system_deps::Config::new().probe() { + let _ = eprintln!("{}", s); + process::exit(1); + } +} diff --git a/gstreamer-gl/x11/sys/src/lib.rs b/gstreamer-gl/x11/sys/src/lib.rs new file mode 100644 index 000000000..78a5cda56 --- /dev/null +++ b/gstreamer-gl/x11/sys/src/lib.rs @@ -0,0 +1,71 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir @ e941700) +// from gir-files (https://github.com/gtk-rs/gir-files @ d2591d00) +// DO NOT EDIT + +#![allow(non_camel_case_types, non_upper_case_globals, non_snake_case)] +#![allow( + clippy::approx_constant, + clippy::type_complexity, + clippy::unreadable_literal +)] +#![cfg_attr(feature = "dox", feature(doc_cfg))] + +use glib_sys as glib; +use gstreamer_gl_sys as gst_gl; + +#[allow(unused_imports)] +use libc::{ + c_char, c_double, c_float, c_int, c_long, c_short, c_uchar, c_uint, c_ulong, c_ushort, c_void, + intptr_t, size_t, ssize_t, time_t, uintptr_t, FILE, +}; + +#[allow(unused_imports)] +use glib::{gboolean, gconstpointer, gpointer, GType}; + +// Records +#[repr(C)] +#[derive(Copy, Clone)] +pub struct GstGLDisplayX11Class { + pub object_class: gst_gl::GstGLDisplayClass, + pub _padding: [gpointer; 4], +} + +impl ::std::fmt::Debug for GstGLDisplayX11Class { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + f.debug_struct(&format!("GstGLDisplayX11Class @ {:?}", self as *const _)) + .field("object_class", &self.object_class) + .field("_padding", &self._padding) + .finish() + } +} + +// Classes +#[repr(C)] +#[derive(Copy, Clone)] +pub struct GstGLDisplayX11 { + pub parent: gst_gl::GstGLDisplay, + pub name: *mut c_char, + pub display: gpointer, + pub xcb_connection: gpointer, + pub foreign_display: gboolean, + pub _padding: [gpointer; 4], +} + +impl ::std::fmt::Debug for GstGLDisplayX11 { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + f.debug_struct(&format!("GstGLDisplayX11 @ {:?}", self as *const _)) + .finish() + } +} + +#[link(name = "gstgl-1.0")] +extern "C" { + + //========================================================================= + // GstGLDisplayX11 + //========================================================================= + pub fn gst_gl_display_x11_get_type() -> GType; + pub fn gst_gl_display_x11_new(name: *const c_char) -> *mut GstGLDisplayX11; + pub fn gst_gl_display_x11_new_with_display(display: gpointer) -> *mut GstGLDisplayX11; + +} diff --git a/gstreamer-gl/x11/sys/tests/abi.rs b/gstreamer-gl/x11/sys/tests/abi.rs new file mode 100644 index 000000000..5ebf89a3f --- /dev/null +++ b/gstreamer-gl/x11/sys/tests/abi.rs @@ -0,0 +1,268 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir @ e941700) +// from gir-files (https://github.com/gtk-rs/gir-files @ d2591d00) +// DO NOT EDIT + +use gst_glx11_sys::*; +use std::env; +use std::error::Error; +use std::mem::{align_of, size_of}; +use std::path::Path; +use std::process::Command; +use std::str; +use tempfile::Builder; + +static PACKAGES: &[&str] = &["gstreamer-gl-x11-1.0"]; + +#[derive(Clone, Debug)] +struct Compiler { + pub args: Vec, +} + +impl Compiler { + pub fn new() -> Result> { + let mut args = get_var("CC", "cc")?; + args.push("-Wno-deprecated-declarations".to_owned()); + // For %z support in printf when using MinGW. + args.push("-D__USE_MINGW_ANSI_STDIO".to_owned()); + args.extend(get_var("CFLAGS", "")?); + args.extend(get_var("CPPFLAGS", "")?); + args.extend(pkg_config_cflags(PACKAGES)?); + Ok(Compiler { args }) + } + + pub fn define<'a, V: Into>>(&mut self, var: &str, val: V) { + let arg = match val.into() { + None => format!("-D{}", var), + Some(val) => format!("-D{}={}", var, val), + }; + self.args.push(arg); + } + + pub fn compile(&self, src: &Path, out: &Path) -> Result<(), Box> { + let mut cmd = self.to_command(); + cmd.arg(src); + cmd.arg("-o"); + cmd.arg(out); + let status = cmd.spawn()?.wait()?; + if !status.success() { + return Err(format!("compilation command {:?} failed, {}", &cmd, status).into()); + } + Ok(()) + } + + fn to_command(&self) -> Command { + let mut cmd = Command::new(&self.args[0]); + cmd.args(&self.args[1..]); + cmd + } +} + +fn get_var(name: &str, default: &str) -> Result, Box> { + match env::var(name) { + Ok(value) => Ok(shell_words::split(&value)?), + Err(env::VarError::NotPresent) => Ok(shell_words::split(default)?), + Err(err) => Err(format!("{} {}", name, err).into()), + } +} + +fn pkg_config_cflags(packages: &[&str]) -> Result, Box> { + if packages.is_empty() { + return Ok(Vec::new()); + } + let mut cmd = Command::new("pkg-config"); + cmd.arg("--cflags"); + cmd.args(packages); + let out = cmd.output()?; + if !out.status.success() { + return Err(format!("command {:?} returned {}", &cmd, out.status).into()); + } + let stdout = str::from_utf8(&out.stdout)?; + Ok(shell_words::split(stdout.trim())?) +} + +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +struct Layout { + size: usize, + alignment: usize, +} + +#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] +struct Results { + /// Number of successfully completed tests. + passed: usize, + /// Total number of failed tests (including those that failed to compile). + failed: usize, + /// Number of tests that failed to compile. + failed_to_compile: usize, +} + +impl Results { + fn record_passed(&mut self) { + self.passed += 1; + } + fn record_failed(&mut self) { + self.failed += 1; + } + fn record_failed_to_compile(&mut self) { + self.failed += 1; + self.failed_to_compile += 1; + } + fn summary(&self) -> String { + format!( + "{} passed; {} failed (compilation errors: {})", + self.passed, self.failed, self.failed_to_compile + ) + } + fn expect_total_success(&self) { + if self.failed == 0 { + println!("OK: {}", self.summary()); + } else { + panic!("FAILED: {}", self.summary()); + }; + } +} + +#[test] +fn cross_validate_constants_with_c() { + let tmpdir = Builder::new() + .prefix("abi") + .tempdir() + .expect("temporary directory"); + let cc = Compiler::new().expect("configured compiler"); + + assert_eq!( + "1", + get_c_value(tmpdir.path(), &cc, "1").expect("C constant"), + "failed to obtain correct constant value for 1" + ); + + let mut results: Results = Default::default(); + for (i, &(name, rust_value)) in RUST_CONSTANTS.iter().enumerate() { + match get_c_value(tmpdir.path(), &cc, name) { + Err(e) => { + results.record_failed_to_compile(); + eprintln!("{}", e); + } + Ok(ref c_value) => { + if rust_value == c_value { + results.record_passed(); + } else { + results.record_failed(); + eprintln!( + "Constant value mismatch for {}\nRust: {:?}\nC: {:?}", + name, rust_value, c_value + ); + } + } + }; + if (i + 1) % 25 == 0 { + println!("constants ... {}", results.summary()); + } + } + results.expect_total_success(); +} + +#[test] +fn cross_validate_layout_with_c() { + let tmpdir = Builder::new() + .prefix("abi") + .tempdir() + .expect("temporary directory"); + let cc = Compiler::new().expect("configured compiler"); + + assert_eq!( + Layout { + size: 1, + alignment: 1 + }, + get_c_layout(tmpdir.path(), &cc, "char").expect("C layout"), + "failed to obtain correct layout for char type" + ); + + let mut results: Results = Default::default(); + for (i, &(name, rust_layout)) in RUST_LAYOUTS.iter().enumerate() { + match get_c_layout(tmpdir.path(), &cc, name) { + Err(e) => { + results.record_failed_to_compile(); + eprintln!("{}", e); + } + Ok(c_layout) => { + if rust_layout == c_layout { + results.record_passed(); + } else { + results.record_failed(); + eprintln!( + "Layout mismatch for {}\nRust: {:?}\nC: {:?}", + name, rust_layout, &c_layout + ); + } + } + }; + if (i + 1) % 25 == 0 { + println!("layout ... {}", results.summary()); + } + } + results.expect_total_success(); +} + +fn get_c_layout(dir: &Path, cc: &Compiler, name: &str) -> Result> { + let exe = dir.join("layout"); + let mut cc = cc.clone(); + cc.define("ABI_TYPE_NAME", name); + cc.compile(Path::new("tests/layout.c"), &exe)?; + + let mut abi_cmd = Command::new(exe); + let output = abi_cmd.output()?; + if !output.status.success() { + return Err(format!("command {:?} failed, {:?}", &abi_cmd, &output).into()); + } + + let stdout = str::from_utf8(&output.stdout)?; + let mut words = stdout.trim().split_whitespace(); + let size = words.next().unwrap().parse().unwrap(); + let alignment = words.next().unwrap().parse().unwrap(); + Ok(Layout { size, alignment }) +} + +fn get_c_value(dir: &Path, cc: &Compiler, name: &str) -> Result> { + let exe = dir.join("constant"); + let mut cc = cc.clone(); + cc.define("ABI_CONSTANT_NAME", name); + cc.compile(Path::new("tests/constant.c"), &exe)?; + + let mut abi_cmd = Command::new(exe); + let output = abi_cmd.output()?; + if !output.status.success() { + return Err(format!("command {:?} failed, {:?}", &abi_cmd, &output).into()); + } + + let output = str::from_utf8(&output.stdout)?.trim(); + if !output.starts_with("###gir test###") || !output.ends_with("###gir test###") { + return Err(format!( + "command {:?} return invalid output, {:?}", + &abi_cmd, &output + ) + .into()); + } + + Ok(String::from(&output[14..(output.len() - 14)])) +} + +const RUST_LAYOUTS: &[(&str, Layout)] = &[ + ( + "GstGLDisplayX11", + Layout { + size: size_of::(), + alignment: align_of::(), + }, + ), + ( + "GstGLDisplayX11Class", + Layout { + size: size_of::(), + alignment: align_of::(), + }, + ), +]; + +const RUST_CONSTANTS: &[(&str, &str)] = &[]; diff --git a/gstreamer-gl/x11/sys/tests/constant.c b/gstreamer-gl/x11/sys/tests/constant.c new file mode 100644 index 000000000..6cd272ba1 --- /dev/null +++ b/gstreamer-gl/x11/sys/tests/constant.c @@ -0,0 +1,27 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir @ e941700) +// from gir-files (https://github.com/gtk-rs/gir-files @ d2591d00) +// DO NOT EDIT + +#include "manual.h" +#include + +int main() { + printf(_Generic((ABI_CONSTANT_NAME), + char *: "###gir test###%s###gir test###\n", + const char *: "###gir test###%s###gir test###\n", + char: "###gir test###%c###gir test###\n", + signed char: "###gir test###%hhd###gir test###\n", + unsigned char: "###gir test###%hhu###gir test###\n", + short int: "###gir test###%hd###gir test###\n", + unsigned short int: "###gir test###%hu###gir test###\n", + int: "###gir test###%d###gir test###\n", + unsigned int: "###gir test###%u###gir test###\n", + long: "###gir test###%ld###gir test###\n", + unsigned long: "###gir test###%lu###gir test###\n", + long long: "###gir test###%lld###gir test###\n", + unsigned long long: "###gir test###%llu###gir test###\n", + double: "###gir test###%f###gir test###\n", + long double: "###gir test###%ld###gir test###\n"), + ABI_CONSTANT_NAME); + return 0; +} diff --git a/gstreamer-gl/x11/sys/tests/layout.c b/gstreamer-gl/x11/sys/tests/layout.c new file mode 100644 index 000000000..166185041 --- /dev/null +++ b/gstreamer-gl/x11/sys/tests/layout.c @@ -0,0 +1,12 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir @ e941700) +// from gir-files (https://github.com/gtk-rs/gir-files @ d2591d00) +// DO NOT EDIT + +#include "manual.h" +#include +#include + +int main() { + printf("%zu\n%zu", sizeof(ABI_TYPE_NAME), alignof(ABI_TYPE_NAME)); + return 0; +} diff --git a/gstreamer-gl/x11/sys/tests/manual.h b/gstreamer-gl/x11/sys/tests/manual.h new file mode 100644 index 000000000..5d5397cf4 --- /dev/null +++ b/gstreamer-gl/x11/sys/tests/manual.h @@ -0,0 +1,3 @@ +// Feel free to edit this file, it won't be regenerated by gir generator unless removed. + +#include