Update to softbuffer 0.3, tracking up to age sets of primitives
This commit is contained in:
parent
070abff5ce
commit
ff268c8c42
3 changed files with 79 additions and 45 deletions
|
|
@ -145,7 +145,7 @@ resvg = "0.36"
|
||||||
rustc-hash = "1.0"
|
rustc-hash = "1.0"
|
||||||
smol = "1.0"
|
smol = "1.0"
|
||||||
smol_str = "0.2"
|
smol_str = "0.2"
|
||||||
softbuffer = "0.2"
|
softbuffer = "0.3.4"
|
||||||
syntect = "5.1"
|
syntect = "5.1"
|
||||||
sysinfo = "0.28"
|
sysinfo = "0.28"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
|
|
|
||||||
|
|
@ -238,6 +238,7 @@ impl Candidate {
|
||||||
default_font: settings.default_font,
|
default_font: settings.default_font,
|
||||||
default_text_size: settings.default_text_size,
|
default_text_size: settings.default_text_size,
|
||||||
},
|
},
|
||||||
|
_compatible_window,
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(Compositor::TinySkia(compositor))
|
Ok(Compositor::TinySkia(compositor))
|
||||||
|
|
|
||||||
|
|
@ -5,18 +5,21 @@ use crate::graphics::{Error, Viewport};
|
||||||
use crate::{Backend, Primitive, Renderer, Settings};
|
use crate::{Backend, Primitive, Renderer, Settings};
|
||||||
|
|
||||||
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
|
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
|
||||||
|
use std::collections::VecDeque;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
use std::num::NonZeroU32;
|
||||||
|
|
||||||
pub struct Compositor<Theme> {
|
pub struct Compositor<Theme> {
|
||||||
|
context: Option<softbuffer::Context>,
|
||||||
settings: Settings,
|
settings: Settings,
|
||||||
_theme: PhantomData<Theme>,
|
_theme: PhantomData<Theme>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Surface {
|
pub struct Surface {
|
||||||
window: softbuffer::GraphicsContext,
|
window: softbuffer::Surface,
|
||||||
buffer: Vec<u32>,
|
|
||||||
clip_mask: tiny_skia::Mask,
|
clip_mask: tiny_skia::Mask,
|
||||||
primitives: Option<Vec<Primitive>>,
|
// Primitives of existing buffers, by decreasing age
|
||||||
|
primitives: VecDeque<Vec<Primitive>>,
|
||||||
background_color: Color,
|
background_color: Color,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -27,9 +30,9 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
|
||||||
|
|
||||||
fn new<W: HasRawWindowHandle + HasRawDisplayHandle>(
|
fn new<W: HasRawWindowHandle + HasRawDisplayHandle>(
|
||||||
settings: Self::Settings,
|
settings: Self::Settings,
|
||||||
_compatible_window: Option<&W>,
|
compatible_window: Option<&W>,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
Ok(new(settings))
|
Ok(new(settings, compatible_window))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_renderer(&self) -> Self::Renderer {
|
fn create_renderer(&self) -> Self::Renderer {
|
||||||
|
|
@ -47,16 +50,21 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
|
||||||
height: u32,
|
height: u32,
|
||||||
) -> Surface {
|
) -> Surface {
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
let window =
|
let window = if let Some(context) = self.context.as_ref() {
|
||||||
unsafe { softbuffer::GraphicsContext::new(window, window) }
|
unsafe { softbuffer::Surface::new(context, window) }
|
||||||
.expect("Create softbuffer for window");
|
.expect("Create softbuffer surface for window")
|
||||||
|
} else {
|
||||||
|
let context = unsafe { softbuffer::Context::new(window) }
|
||||||
|
.expect("Create softbuffer context for window");
|
||||||
|
unsafe { softbuffer::Surface::new(&context, window) }
|
||||||
|
.expect("Create softbuffer surface for window")
|
||||||
|
};
|
||||||
|
|
||||||
Surface {
|
Surface {
|
||||||
window,
|
window,
|
||||||
buffer: vec![0; width as usize * height as usize],
|
|
||||||
clip_mask: tiny_skia::Mask::new(width, height)
|
clip_mask: tiny_skia::Mask::new(width, height)
|
||||||
.expect("Create clip mask"),
|
.expect("Create clip mask"),
|
||||||
primitives: None,
|
primitives: VecDeque::new(),
|
||||||
background_color: Color::BLACK,
|
background_color: Color::BLACK,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -67,10 +75,9 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
|
||||||
width: u32,
|
width: u32,
|
||||||
height: u32,
|
height: u32,
|
||||||
) {
|
) {
|
||||||
surface.buffer.resize((width * height) as usize, 0);
|
|
||||||
surface.clip_mask =
|
surface.clip_mask =
|
||||||
tiny_skia::Mask::new(width, height).expect("Create clip mask");
|
tiny_skia::Mask::new(width, height).expect("Create clip mask");
|
||||||
surface.primitives = None;
|
surface.primitives.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch_information(&self) -> Information {
|
fn fetch_information(&self) -> Information {
|
||||||
|
|
@ -121,8 +128,15 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new<Theme>(settings: Settings) -> Compositor<Theme> {
|
pub fn new<W: HasRawWindowHandle + HasRawDisplayHandle, Theme>(
|
||||||
|
settings: Settings,
|
||||||
|
compatible_window: Option<&W>,
|
||||||
|
) -> Compositor<Theme> {
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
let context = compatible_window
|
||||||
|
.and_then(|w| unsafe { softbuffer::Context::new(w) }.ok());
|
||||||
Compositor {
|
Compositor {
|
||||||
|
context,
|
||||||
settings,
|
settings,
|
||||||
_theme: PhantomData,
|
_theme: PhantomData,
|
||||||
}
|
}
|
||||||
|
|
@ -139,48 +153,67 @@ pub fn present<T: AsRef<str>>(
|
||||||
let physical_size = viewport.physical_size();
|
let physical_size = viewport.physical_size();
|
||||||
let scale_factor = viewport.scale_factor() as f32;
|
let scale_factor = viewport.scale_factor() as f32;
|
||||||
|
|
||||||
let mut pixels = tiny_skia::PixmapMut::from_bytes(
|
surface
|
||||||
bytemuck::cast_slice_mut(&mut surface.buffer),
|
.window
|
||||||
physical_size.width,
|
.resize(
|
||||||
physical_size.height,
|
NonZeroU32::new(physical_size.width).unwrap(),
|
||||||
)
|
NonZeroU32::new(physical_size.height).unwrap(),
|
||||||
.expect("Create pixel map");
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let damage = surface
|
// TODO Add variants to `SurfaceError`?
|
||||||
.primitives
|
let mut buffer = surface
|
||||||
.as_deref()
|
.window
|
||||||
|
.buffer_mut()
|
||||||
|
.map_err(|_| compositor::SurfaceError::Lost)?;
|
||||||
|
|
||||||
|
let age = buffer.age();
|
||||||
|
|
||||||
|
// Forget primatives for back buffers older than `age`
|
||||||
|
// Or if this is a new buffer, keep at most two.
|
||||||
|
let max = if age == 0 { 2 } else { age };
|
||||||
|
while surface.primitives.len() as u8 > max {
|
||||||
|
let _ = surface.primitives.pop_front();
|
||||||
|
}
|
||||||
|
|
||||||
|
let last_primitives = if surface.primitives.len() as u8 == age {
|
||||||
|
surface.primitives.pop_front()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let damage = last_primitives
|
||||||
.and_then(|last_primitives| {
|
.and_then(|last_primitives| {
|
||||||
(surface.background_color == background_color)
|
(surface.background_color == background_color)
|
||||||
.then(|| damage::list(last_primitives, primitives))
|
.then(|| damage::list(&last_primitives, primitives))
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| vec![Rectangle::with_size(viewport.logical_size())]);
|
.unwrap_or_else(|| vec![Rectangle::with_size(viewport.logical_size())]);
|
||||||
|
|
||||||
if damage.is_empty() {
|
surface.primitives.push_back(primitives.to_vec());
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
surface.primitives = Some(primitives.to_vec());
|
|
||||||
surface.background_color = background_color;
|
surface.background_color = background_color;
|
||||||
|
|
||||||
let damage = damage::group(damage, scale_factor, physical_size);
|
if !damage.is_empty() {
|
||||||
|
let damage = damage::group(damage, scale_factor, physical_size);
|
||||||
|
|
||||||
backend.draw(
|
let mut pixels = tiny_skia::PixmapMut::from_bytes(
|
||||||
&mut pixels,
|
bytemuck::cast_slice_mut(&mut buffer),
|
||||||
&mut surface.clip_mask,
|
physical_size.width,
|
||||||
primitives,
|
physical_size.height,
|
||||||
viewport,
|
)
|
||||||
&damage,
|
.expect("Create pixel map");
|
||||||
background_color,
|
|
||||||
overlay,
|
|
||||||
);
|
|
||||||
|
|
||||||
surface.window.set_buffer(
|
backend.draw(
|
||||||
&surface.buffer,
|
&mut pixels,
|
||||||
physical_size.width as u16,
|
&mut surface.clip_mask,
|
||||||
physical_size.height as u16,
|
primitives,
|
||||||
);
|
viewport,
|
||||||
|
&damage,
|
||||||
|
background_color,
|
||||||
|
overlay,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
buffer.present().map_err(|_| compositor::SurfaceError::Lost)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn screenshot<T: AsRef<str>>(
|
pub fn screenshot<T: AsRef<str>>(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue