update cushy + improved layout

This commit is contained in:
Daniel Bulant 2024-11-25 15:23:12 +01:00
parent ffaef580df
commit d2123ba96e
No known key found for this signature in database
4 changed files with 88 additions and 61 deletions

24
Cargo.lock generated
View file

@ -823,7 +823,7 @@ checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991"
[[package]] [[package]]
name = "cushy" name = "cushy"
version = "0.4.0" version = "0.4.0"
source = "git+https://github.com/khonsulabs/cushy.git?branch=main#57f0c06b12f51cd7ef133794119bf1ba163e88d8" source = "git+https://github.com/khonsulabs/cushy.git?branch=main#5e2819a98386a4d1f7485de23acd6603e43b6368"
dependencies = [ dependencies = [
"ahash", "ahash",
"alot", "alot",
@ -852,7 +852,7 @@ dependencies = [
[[package]] [[package]]
name = "cushy-macros" name = "cushy-macros"
version = "0.4.0" version = "0.4.0"
source = "git+https://github.com/khonsulabs/cushy.git?branch=main#57f0c06b12f51cd7ef133794119bf1ba163e88d8" source = "git+https://github.com/khonsulabs/cushy.git?branch=main#5e2819a98386a4d1f7485de23acd6603e43b6368"
dependencies = [ dependencies = [
"attribute-derive", "attribute-derive",
"manyhow", "manyhow",
@ -1576,9 +1576,9 @@ dependencies = [
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.15.1" version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
[[package]] [[package]]
name = "heck" name = "heck"
@ -1798,7 +1798,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
dependencies = [ dependencies = [
"equivalent", "equivalent",
"hashbrown 0.15.1", "hashbrown 0.15.2",
] ]
[[package]] [[package]]
@ -1926,7 +1926,7 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
[[package]] [[package]]
name = "kludgine" name = "kludgine"
version = "0.11.0" version = "0.11.0"
source = "git+https://github.com/khonsulabs/kludgine#1964cea13c1da08fb06d93c5101f3cd1f748c930" source = "git+https://github.com/khonsulabs/kludgine#af4e6450c3bff3b2b6a6a3d7e9c0c2471b622578"
dependencies = [ dependencies = [
"ahash", "ahash",
"alot", "alot",
@ -4129,9 +4129,9 @@ checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082"
[[package]] [[package]]
name = "wgpu" name = "wgpu"
version = "23.0.0" version = "23.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76ab52f2d3d18b70d5ab8dd270a1cff3ebe6dbe4a7d13c1cc2557138a9777fdc" checksum = "80f70000db37c469ea9d67defdc13024ddf9a5f1b89cb2941b812ad7cde1735a"
dependencies = [ dependencies = [
"arrayvec", "arrayvec",
"cfg_aliases 0.1.1", "cfg_aliases 0.1.1",
@ -4154,9 +4154,9 @@ dependencies = [
[[package]] [[package]]
name = "wgpu-core" name = "wgpu-core"
version = "23.0.0" version = "23.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e0c68e7b6322a03ee5b83fcd92caeac5c2a932f6457818179f4652ad2a9c065" checksum = "d63c3c478de8e7e01786479919c8769f62a22eec16788d8c2ac77ce2c132778a"
dependencies = [ dependencies = [
"arrayvec", "arrayvec",
"bit-vec", "bit-vec",
@ -4179,9 +4179,9 @@ dependencies = [
[[package]] [[package]]
name = "wgpu-hal" name = "wgpu-hal"
version = "23.0.0" version = "23.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de6e7266b869de56c7e3ed72a954899f71d14fec6cc81c102b7530b92947601b" checksum = "89364b8a0b211adc7b16aeaf1bd5ad4a919c1154b44c9ce27838213ba05fd821"
dependencies = [ dependencies = [
"android_system_properties", "android_system_properties",
"arrayvec", "arrayvec",

View file

@ -7,7 +7,10 @@ use std::{
}; };
use cushy::{ use cushy::{
figures::{units::UPx, Rect}, figures::{
units::{Px, UPx},
IntoUnsigned, Rect,
},
kludgine::{self, wgpu}, kludgine::{self, wgpu},
RenderOperation, RenderOperation,
}; };
@ -304,7 +307,7 @@ impl VideoPipeline {
} }
} }
fn prepare(&mut self, queue: &wgpu::Queue, video_id: u64, bounds: Rect<UPx>) { fn prepare(&mut self, queue: &wgpu::Queue, video_id: u64, bounds: Rect<Px>) {
if let Some(video) = self.videos.get(&video_id) { if let Some(video) = self.videos.get(&video_id) {
let uniforms = Uniforms { let uniforms = Uniforms {
rect: [ rect: [
@ -327,38 +330,23 @@ impl VideoPipeline {
fn draw(&self, pass: &mut wgpu::RenderPass, viewport: Rect<UPx>, video_id: u64) { fn draw(&self, pass: &mut wgpu::RenderPass, viewport: Rect<UPx>, video_id: u64) {
if let Some(video) = self.videos.get(&video_id) { if let Some(video) = self.videos.get(&video_id) {
// let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
// label: Some("iced_video_player render pass"),
// color_attachments: &[Some(wgpu::RenderPassColorAttachment {
// view: target,
// resolve_target: None,
// ops: wgpu::Operations {
// load: wgpu::LoadOp::Load,
// store: wgpu::StoreOp::Store,
// },
// })],
// depth_stencil_attachment: None,
// timestamp_writes: None,
// occlusion_query_set: None,
// });
pass.set_pipeline(&self.pipeline); pass.set_pipeline(&self.pipeline);
pass.set_bind_group(0, &video.bg0, &[]); pass.set_bind_group(0, &video.bg0, &[]);
// pass.set_viewport( pass.set_viewport(
// viewport.origin.x as _, viewport.origin.x.get() as _,
// viewport.origin.y as _, viewport.origin.y.get() as _,
// viewport.size.width as _, viewport.size.width.get() as f32,
// viewport.size.height as _, viewport.size.height.get() as f32,
// 0.0, 0.0,
// 1.0, 1.0,
// ); );
pass.draw(0..4, 0..1); pass.draw(0..4, 0..1);
} }
} }
} }
pub(crate) struct VideoRO { pub(crate) struct VideoRO {
pipeline: Option<VideoPipeline>, pipeline: VideoPipeline,
} }
impl RenderOperation for VideoRO { impl RenderOperation for VideoRO {
@ -366,21 +354,19 @@ impl RenderOperation for VideoRO {
type Prepared = VideoPrimitive; type Prepared = VideoPrimitive;
fn new(graphics: &mut cushy::kludgine::Graphics<'_>) -> Self { fn new(graphics: &mut cushy::kludgine::Graphics<'_>) -> Self {
VideoRO { pipeline: None } VideoRO {
pipeline: VideoPipeline::new(graphics),
}
} }
fn prepare( fn prepare(
&mut self, &mut self,
context: Self::DrawInfo, context: Self::DrawInfo,
origin: cushy::figures::Point<cushy::figures::units::Px>, rect: Rect<Px>,
graphics: &mut cushy::kludgine::Graphics<'_>, graphics: &mut cushy::kludgine::Graphics<'_>,
) -> Self::Prepared { ) -> Self::Prepared {
let pipeline = self
.pipeline
.get_or_insert_with(|| VideoPipeline::new(graphics));
if context.upload_frame { if context.upload_frame {
pipeline.upload( self.pipeline.upload(
graphics.device(), graphics.device(),
graphics.queue(), graphics.queue(),
context.video_id, context.video_id,
@ -389,26 +375,22 @@ impl RenderOperation for VideoRO {
context.frame.lock().expect("lock frame mutex").as_slice(), context.frame.lock().expect("lock frame mutex").as_slice(),
); );
} }
self.pipeline
pipeline.prepare(graphics.queue(), context.video_id, graphics.clip_rect()); .prepare(graphics.queue(), context.video_id, rect);
context context
} }
fn render( fn render(
&self, &self,
prepared: &Self::Prepared, prepared: &Self::Prepared,
origin: cushy::figures::Point<cushy::figures::units::Px>, _rect: Rect<Px>,
opacity: f32, _opacity: f32,
graphics: &mut cushy::kludgine::RenderingGraphics<'_, '_>, graphics: &mut cushy::kludgine::RenderingGraphics<'_, '_>,
) { ) {
let pipeline = self.pipeline.as_ref().expect("prepare sets pipeline");
let rect = graphics.clip_rect(); let rect = graphics.clip_rect();
pipeline.draw( dbg!(rect);
// target, self.pipeline
graphics.pass_mut(), .draw(graphics.pass_mut(), rect.into_unsigned(), prepared.video_id);
rect,
prepared.video_id,
);
} }
} }

View file

@ -5,15 +5,19 @@ use std::{
use cushy::{ use cushy::{
context::{GraphicsContext, LayoutContext}, context::{GraphicsContext, LayoutContext},
figures::{units::UPx, Size}, figures::{
value::{Destination, Dynamic, DynamicReader, Generation, Source}, units::{Px, UPx},
FloatConversion, IntoSigned, IntoUnsigned, Point, Rect, Size,
},
value::{Destination, Dynamic, DynamicReader, Generation, Source, Value},
widget::Widget, widget::Widget,
widgets::image::{Aspect, ImageScaling},
ConstraintLimit, ConstraintLimit,
}; };
use crate::{ use crate::{
pipeline::{VideoPrimitive, VideoRO}, pipeline::{VideoPrimitive, VideoRO},
video::Video, video::{Internal, Video},
Error, Error,
}; };
@ -26,6 +30,7 @@ pub struct VideoPlayer {
subtitles: Dynamic<Option<String>>, subtitles: Dynamic<Option<String>>,
frame: Dynamic<()>, frame: Dynamic<()>,
last_frame: Generation, last_frame: Generation,
scaling: Value<ImageScaling>,
} }
impl VideoPlayer { impl VideoPlayer {
@ -37,6 +42,7 @@ impl VideoPlayer {
video, video,
last_frame: Generation::default(), last_frame: Generation::default(),
frame, frame,
scaling: Default::default(),
} }
} }
@ -61,6 +67,41 @@ impl VideoPlayer {
pub fn video(&self) -> &Video { pub fn video(&self) -> &Video {
&self.video &self.video
} }
fn calculate_video_rect(
&self,
video: &Internal,
within_size: Size<UPx>,
context: &mut GraphicsContext<'_, '_, '_, '_>,
) -> Rect<Px> {
let within_size = within_size.into_signed();
let size = Size {
width: Px::new(video.width),
height: Px::new(video.height),
};
match self.scaling.get_tracking_invalidate(context) {
ImageScaling::Aspect { mode, orientation } => {
let scale_width = within_size.width.into_float() / size.width.into_float();
let scale_height = within_size.height.into_float() / size.height.into_float();
let effective_scale = match mode {
Aspect::Fill => scale_width.max(scale_height),
Aspect::Fit => scale_width.min(scale_height),
};
let scaled = size * effective_scale;
let x = (within_size.width - scaled.width) * *orientation.width;
let y = (within_size.height - scaled.height) * *orientation.height;
Rect::new(Point::new(x, y), scaled)
}
ImageScaling::Stretch => within_size.into(),
ImageScaling::Scale(factor) => {
let size = size.map(|px| px * factor);
size.into()
}
}
}
} }
impl Widget for VideoPlayer { impl Widget for VideoPlayer {
@ -93,8 +134,11 @@ impl Widget for VideoPlayer {
fn layout( fn layout(
&mut self, &mut self,
available_space: Size<ConstraintLimit>, available_space: Size<ConstraintLimit>,
_context: &mut LayoutContext<'_, '_, '_, '_>, context: &mut LayoutContext<'_, '_, '_, '_>,
) -> Size<UPx> { ) -> Size<UPx> {
available_space.map(ConstraintLimit::max) let inner = self.video.read();
let rect =
self.calculate_video_rect(&inner, available_space.map(ConstraintLimit::max), context);
rect.size.into_unsigned()
} }
} }

View file

@ -1,6 +1,7 @@
// This file is taken nearly one to one from https://github.com/jazzfool/iced_video_player // This file is taken nearly one to one from https://github.com/jazzfool/iced_video_player
use crate::Error; use crate::Error;
use cushy::value::{Destination, Dynamic}; use cushy::value::{Destination, Dynamic};
use glib::property::PropertyGet;
use gstreamer as gst; use gstreamer as gst;
use gstreamer_app as gst_app; use gstreamer_app as gst_app;
use gstreamer_app::prelude::*; use gstreamer_app::prelude::*;