summaryrefslogtreecommitdiffstats
path: root/graphics
diff options
context:
space:
mode:
Diffstat (limited to 'graphics')
-rw-r--r--graphics/Cargo.toml1
-rw-r--r--graphics/src/backend.rs12
-rw-r--r--graphics/src/compositor.rs15
-rw-r--r--graphics/src/gradient.rs82
-rw-r--r--graphics/src/lib.rs1
-rw-r--r--graphics/src/renderer.rs28
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));