diff --git a/Cargo.lock b/Cargo.lock index 03178df..e604270 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1404,6 +1404,7 @@ dependencies = [ "objc2-foundation", "parking_lot", "percent-encoding", + "pollster", "raw-window-handle 0.5.2", "raw-window-handle 0.6.2", "ron", @@ -1413,6 +1414,7 @@ dependencies = [ "wasm-bindgen-futures", "web-sys", "web-time", + "wgpu", "winapi", "winit", ] @@ -3470,6 +3472,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "pollster" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2" + [[package]] name = "powerfmt" version = "0.2.0" @@ -4890,6 +4898,7 @@ dependencies = [ "document-features", "js-sys", "log", + "naga", "parking_lot", "profiling", "raw-window-handle 0.6.2", @@ -4940,6 +4949,7 @@ dependencies = [ "arrayvec", "ash", "bitflags 2.6.0", + "block", "cfg_aliases", "core-graphics-types", "glow", diff --git a/crates/gui/Cargo.toml b/crates/gui/Cargo.toml index cf85b53..6a8a14a 100644 --- a/crates/gui/Cargo.toml +++ b/crates/gui/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/valadaptive/ntsc-rs/tree/main/crates/gui" [dependencies] ntscrs = { path = "../ntscrs" } arboard = "3.4.0" -eframe = { version = "0.28.1", features=["persistence"] } +eframe = { version = "0.28.1", features=["persistence", "wgpu"] } # The dirs maintainer has intentionally inserted an MPL dependency into this package. # https://github.com/dirs-dev/dirs-sys-rs/issues/21 # May his shoe forever contain a small pebble in it for making me waste time on this garbage. diff --git a/crates/gui/src/app/main.rs b/crates/gui/src/app/main.rs index eeeb942..34787a3 100644 --- a/crates/gui/src/app/main.rs +++ b/crates/gui/src/app/main.rs @@ -390,10 +390,10 @@ impl NtscApp { let tex = ctx.load_texture( "preview", - egui::ColorImage::from_rgb([0, 0], &[]), + egui::ColorImage::from_rgb([1, 1], &[0, 0, 0]), egui::TextureOptions::LINEAR, ); - let tex_sink = SinkTexture(Some(tex.clone())); + let tex_sink = SinkTexture::new(tex.clone()); let egui_ctx = EguiCtx(Some(ctx.clone())); let video_sink = gstreamer::ElementFactory::make("eguisink") .property("texture", tex_sink) @@ -1835,9 +1835,7 @@ impl NtscApp { ui.with_layout( egui::Layout::centered_and_justified(egui::Direction::LeftToRight), |ui| { - let Some(PipelineInfo { - preview, egui_sink, .. - }) = &mut self.pipeline + let Some(PipelineInfo { egui_sink, .. }) = &mut self.pipeline else { ui.add( egui::Label::new( @@ -1848,10 +1846,19 @@ impl NtscApp { return; }; - if preview.size().iter().any(|dim| *dim == 0) { + let texture = { + let egui_sink = + egui_sink.downcast_ref::().unwrap(); + let egui_sink = EguiSink::from_obj(egui_sink); + egui_sink.get_texture() + }; + + let (Some(preview), true) = + (texture.handle, texture.rendered_at_least_once) + else { ui.add(egui::Spinner::new()); return; - } + }; let texture_size = if self.video_scale.enabled { let texture_actual_size = preview.size_vec2(); diff --git a/crates/gui/src/gst_utils/egui_sink.rs b/crates/gui/src/gst_utils/egui_sink.rs index ec92aee..1a3f2ff 100644 --- a/crates/gui/src/gst_utils/egui_sink.rs +++ b/crates/gui/src/gst_utils/egui_sink.rs @@ -14,7 +14,19 @@ use super::process_gst_frame::process_gst_frame; #[derive(Clone, glib::Boxed, Default)] #[boxed_type(name = "SinkTexture")] -pub struct SinkTexture(pub Option); +pub struct SinkTexture { + pub handle: Option, + pub rendered_at_least_once: bool, +} + +impl SinkTexture { + pub fn new(handle: TextureHandle) -> Self { + Self { + handle: Some(handle), + rendered_at_least_once: false, + } + } +} #[derive(Debug, Clone, Copy, PartialEq, glib::Boxed, Default)] #[boxed_type(name = "VideoPreviewSetting")] @@ -27,21 +39,16 @@ pub enum EffectPreviewSetting { impl Debug for SinkTexture { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let mut t = f.debug_tuple("SinkTexture"); - - match &self.0 { - Some(_) => { - t.field(&"TextureHandle"); - } - None => { - t.field(&"None"); - } - } - - t.finish() + f.debug_struct("SinkTexture") + .field("rendered_at_least_once", &self.rendered_at_least_once) + .finish() } } +#[derive(Debug, Clone, glib::Boxed, Default)] +#[boxed_type(name = "EguiCtx")] +pub struct EguiCtx(pub Option); + #[derive(glib::Properties, Default)] #[properties(wrapper_type = super::elements::EguiSink)] pub struct EguiSink { @@ -63,10 +70,6 @@ pub struct EguiSink { >, } -#[derive(Debug, Clone, glib::Boxed, Default)] -#[boxed_type(name = "EguiCtx")] -pub struct EguiCtx(pub Option); - impl EguiSink { fn set_settings(&self, value: NtscFilterSettings) { *self.settings.lock().unwrap() = value; @@ -107,6 +110,10 @@ impl EguiSink { Ok(image) } + pub fn get_texture(&self) -> SinkTexture { + self.texture.lock().unwrap().clone() + } + pub fn update_texture(&self) -> Result<(), gstreamer::FlowError> { let mut tex = self.texture.lock().unwrap(); let vframe = self.last_frame.lock().unwrap(); @@ -144,7 +151,7 @@ impl EguiSink { } } - tex.0.as_mut().ok_or(gstreamer::FlowError::Error)?.set( + tex.handle.as_mut().ok_or(gstreamer::FlowError::Error)?.set( image, TextureOptions { magnification: TextureFilter::Nearest, @@ -152,6 +159,7 @@ impl EguiSink { ..Default::default() }, ); + tex.rendered_at_least_once = true; if let Some(ctx) = &self.ctx.lock().unwrap().0 { ctx.request_repaint(); }