diff options
Diffstat (limited to 'graphics')
-rw-r--r-- | graphics/Cargo.toml | 1 | ||||
-rw-r--r-- | graphics/src/backend.rs | 12 | ||||
-rw-r--r-- | graphics/src/compositor.rs | 15 | ||||
-rw-r--r-- | graphics/src/gradient.rs | 82 | ||||
-rw-r--r-- | graphics/src/lib.rs | 1 | ||||
-rw-r--r-- | graphics/src/renderer.rs | 28 |
6 files changed, 83 insertions, 56 deletions
diff --git a/graphics/Cargo.toml b/graphics/Cargo.toml index 0e22227d..02621695 100644 --- a/graphics/Cargo.toml +++ b/graphics/Cargo.toml @@ -18,6 +18,7 @@ web-colors = [] [dependencies] glam = "0.24" +half = "2.2.1" log = "0.4" raw-window-handle = "0.5" thiserror = "1.0" diff --git a/graphics/src/backend.rs b/graphics/src/backend.rs index ae89da06..6a082576 100644 --- a/graphics/src/backend.rs +++ b/graphics/src/backend.rs @@ -6,18 +6,6 @@ use iced_core::{Font, Point, Size}; use std::borrow::Cow; -/// The graphics backend of a [`Renderer`]. -/// -/// [`Renderer`]: crate::Renderer -pub trait Backend { - /// Trims the measurements cache. - /// - /// This method is currently necessary to properly trim the text cache in - /// `iced_wgpu` and `iced_glow` because of limitations in the text rendering - /// pipeline. It will be removed in the future. - fn trim_measurements(&mut self) {} -} - /// A graphics backend that supports text rendering. pub trait Text { /// The icon font of the backend. diff --git a/graphics/src/compositor.rs b/graphics/src/compositor.rs index d55e801a..f7b86045 100644 --- a/graphics/src/compositor.rs +++ b/graphics/src/compositor.rs @@ -59,6 +59,19 @@ pub trait Compositor: Sized { background_color: Color, overlay: &[T], ) -> Result<(), SurfaceError>; + + /// Screenshots the current [`Renderer`] primitives to an offscreen texture, and returns the bytes of + /// the texture ordered as `RGBA` in the sRGB color space. + /// + /// [`Renderer`]: Self::Renderer; + fn screenshot<T: AsRef<str>>( + &mut self, + renderer: &mut Self::Renderer, + surface: &mut Self::Surface, + viewport: &Viewport, + background_color: Color, + overlay: &[T], + ) -> Vec<u8>; } /// Result of an unsuccessful call to [`Compositor::present`]. @@ -82,7 +95,7 @@ pub enum SurfaceError { OutOfMemory, } -/// Contains informations about the graphics (e.g. graphics adapter, graphics backend). +/// Contains information about the graphics (e.g. graphics adapter, graphics backend). #[derive(Debug)] pub struct Information { /// Contains the graphics adapter. diff --git a/graphics/src/gradient.rs b/graphics/src/gradient.rs index d26b5665..3f5d0509 100644 --- a/graphics/src/gradient.rs +++ b/graphics/src/gradient.rs @@ -7,6 +7,7 @@ use crate::color; use crate::core::gradient::ColorStop; use crate::core::{self, Color, Point, Rectangle}; +use half::f16; use std::cmp::Ordering; #[derive(Debug, Clone, PartialEq)] @@ -99,61 +100,96 @@ impl Linear { /// Packs the [`Gradient`] for use in shader code. pub fn pack(&self) -> Packed { - let mut data: [f32; 44] = [0.0; 44]; + let mut colors = [[0u32; 2]; 8]; + let mut offsets = [f16::from(0u8); 8]; for (index, stop) in self.stops.iter().enumerate() { let [r, g, b, a] = color::pack(stop.map_or(Color::default(), |s| s.color)) .components(); - data[index * 4] = r; - data[(index * 4) + 1] = g; - data[(index * 4) + 2] = b; - data[(index * 4) + 3] = a; + colors[index] = [ + pack_f16s([f16::from_f32(r), f16::from_f32(g)]), + pack_f16s([f16::from_f32(b), f16::from_f32(a)]), + ]; - data[32 + index] = stop.map_or(2.0, |s| s.offset); + offsets[index] = + stop.map_or(f16::from_f32(2.0), |s| f16::from_f32(s.offset)); } - data[40] = self.start.x; - data[41] = self.start.y; - data[42] = self.end.x; - data[43] = self.end.y; + let offsets = [ + pack_f16s([offsets[0], offsets[1]]), + pack_f16s([offsets[2], offsets[3]]), + pack_f16s([offsets[4], offsets[5]]), + pack_f16s([offsets[6], offsets[7]]), + ]; - Packed(data) + let direction = [self.start.x, self.start.y, self.end.x, self.end.y]; + + Packed { + colors, + offsets, + direction, + } } } /// Packed [`Gradient`] data for use in shader code. #[derive(Debug, Copy, Clone, PartialEq)] #[repr(C)] -pub struct Packed([f32; 44]); +pub struct Packed { + // 8 colors, each channel = 16 bit float, 2 colors packed into 1 u32 + colors: [[u32; 2]; 8], + // 8 offsets, 8x 16 bit floats packed into 4 u32s + offsets: [u32; 4], + direction: [f32; 4], +} /// Creates a new [`Packed`] gradient for use in shader code. pub fn pack(gradient: &core::Gradient, bounds: Rectangle) -> Packed { match gradient { core::Gradient::Linear(linear) => { - let mut data: [f32; 44] = [0.0; 44]; + let mut colors = [[0u32; 2]; 8]; + let mut offsets = [f16::from(0u8); 8]; for (index, stop) in linear.stops.iter().enumerate() { let [r, g, b, a] = color::pack(stop.map_or(Color::default(), |s| s.color)) .components(); - data[index * 4] = r; - data[(index * 4) + 1] = g; - data[(index * 4) + 2] = b; - data[(index * 4) + 3] = a; - data[32 + index] = stop.map_or(2.0, |s| s.offset); + colors[index] = [ + pack_f16s([f16::from_f32(r), f16::from_f32(g)]), + pack_f16s([f16::from_f32(b), f16::from_f32(a)]), + ]; + + offsets[index] = stop + .map_or(f16::from_f32(2.0), |s| f16::from_f32(s.offset)); } + let offsets = [ + pack_f16s([offsets[0], offsets[1]]), + pack_f16s([offsets[2], offsets[3]]), + pack_f16s([offsets[4], offsets[5]]), + pack_f16s([offsets[6], offsets[7]]), + ]; + let (start, end) = linear.angle.to_distance(&bounds); - data[40] = start.x; - data[41] = start.y; - data[42] = end.x; - data[43] = end.y; + let direction = [start.x, start.y, end.x, end.y]; - Packed(data) + Packed { + colors, + offsets, + direction, + } } } } + +/// Packs two f16s into one u32. +fn pack_f16s(f: [f16; 2]) -> u32 { + let one = (f[0].to_bits() as u32) << 16; + let two = f[1].to_bits() as u32; + + one | two +} diff --git a/graphics/src/lib.rs b/graphics/src/lib.rs index f6bc87fb..226b245b 100644 --- a/graphics/src/lib.rs +++ b/graphics/src/lib.rs @@ -41,7 +41,6 @@ pub mod geometry; pub mod image; pub use antialiasing::Antialiasing; -pub use backend::Backend; pub use compositor::Compositor; pub use error::Error; pub use gradient::Gradient; diff --git a/graphics/src/renderer.rs b/graphics/src/renderer.rs index de905503..4241d45c 100644 --- a/graphics/src/renderer.rs +++ b/graphics/src/renderer.rs @@ -1,5 +1,5 @@ //! Create a renderer from a [`Backend`]. -use crate::backend::{self, Backend}; +use crate::backend; use crate::Primitive; use iced_core::image; @@ -16,13 +16,13 @@ use std::marker::PhantomData; /// A backend-agnostic renderer that supports all the built-in widgets. #[derive(Debug)] -pub struct Renderer<B: Backend, Theme> { +pub struct Renderer<B, Theme> { backend: B, primitives: Vec<Primitive>, theme: PhantomData<Theme>, } -impl<B: Backend, T> Renderer<B, T> { +impl<B, T> Renderer<B, T> { /// Creates a new [`Renderer`] from the given [`Backend`]. pub fn new(backend: B) -> Self { Self { @@ -52,10 +52,7 @@ impl<B: Backend, T> Renderer<B, T> { } } -impl<B, T> iced_core::Renderer for Renderer<B, T> -where - B: Backend, -{ +impl<B, T> iced_core::Renderer for Renderer<B, T> { type Theme = T; fn layout<Message>( @@ -63,11 +60,7 @@ where element: &Element<'_, Message, Self>, limits: &layout::Limits, ) -> layout::Node { - let layout = element.as_widget().layout(self, limits); - - self.backend.trim_measurements(); - - layout + element.as_widget().layout(self, limits) } fn with_layer(&mut self, bounds: Rectangle, f: impl FnOnce(&mut Self)) { @@ -116,7 +109,7 @@ where impl<B, T> text::Renderer for Renderer<B, T> where - B: Backend + backend::Text, + B: backend::Text, { type Font = Font; @@ -195,7 +188,7 @@ where impl<B, T> image::Renderer for Renderer<B, T> where - B: Backend + backend::Image, + B: backend::Image, { type Handle = image::Handle; @@ -210,7 +203,7 @@ where impl<B, T> svg::Renderer for Renderer<B, T> where - B: Backend + backend::Svg, + B: backend::Svg, { fn dimensions(&self, handle: &svg::Handle) -> Size<u32> { self.backend().viewport_dimensions(handle) @@ -231,10 +224,7 @@ where } #[cfg(feature = "geometry")] -impl<B, T> crate::geometry::Renderer for Renderer<B, T> -where - B: Backend, -{ +impl<B, T> crate::geometry::Renderer for Renderer<B, T> { fn draw(&mut self, layers: Vec<crate::Geometry>) { self.primitives .extend(layers.into_iter().map(crate::Geometry::into)); |