Skip to content

Commit ff268c8

Browse files
committed
Update to softbuffer 0.3, tracking up to age sets of primitives
1 parent 070abff commit ff268c8

3 files changed

Lines changed: 79 additions & 45 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ resvg = "0.36"
145145
rustc-hash = "1.0"
146146
smol = "1.0"
147147
smol_str = "0.2"
148-
softbuffer = "0.2"
148+
softbuffer = "0.3.4"
149149
syntect = "5.1"
150150
sysinfo = "0.28"
151151
thiserror = "1.0"

renderer/src/compositor.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ impl Candidate {
238238
default_font: settings.default_font,
239239
default_text_size: settings.default_text_size,
240240
},
241+
_compatible_window,
241242
);
242243

243244
Ok(Compositor::TinySkia(compositor))

tiny_skia/src/window/compositor.rs

Lines changed: 77 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,21 @@ use crate::graphics::{Error, Viewport};
55
use crate::{Backend, Primitive, Renderer, Settings};
66

77
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
8+
use std::collections::VecDeque;
89
use std::marker::PhantomData;
10+
use std::num::NonZeroU32;
911

1012
pub struct Compositor<Theme> {
13+
context: Option<softbuffer::Context>,
1114
settings: Settings,
1215
_theme: PhantomData<Theme>,
1316
}
1417

1518
pub struct Surface {
16-
window: softbuffer::GraphicsContext,
17-
buffer: Vec<u32>,
19+
window: softbuffer::Surface,
1820
clip_mask: tiny_skia::Mask,
19-
primitives: Option<Vec<Primitive>>,
21+
// Primitives of existing buffers, by decreasing age
22+
primitives: VecDeque<Vec<Primitive>>,
2023
background_color: Color,
2124
}
2225

@@ -27,9 +30,9 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
2730

2831
fn new<W: HasRawWindowHandle + HasRawDisplayHandle>(
2932
settings: Self::Settings,
30-
_compatible_window: Option<&W>,
33+
compatible_window: Option<&W>,
3134
) -> Result<Self, Error> {
32-
Ok(new(settings))
35+
Ok(new(settings, compatible_window))
3336
}
3437

3538
fn create_renderer(&self) -> Self::Renderer {
@@ -47,16 +50,21 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
4750
height: u32,
4851
) -> Surface {
4952
#[allow(unsafe_code)]
50-
let window =
51-
unsafe { softbuffer::GraphicsContext::new(window, window) }
52-
.expect("Create softbuffer for window");
53+
let window = if let Some(context) = self.context.as_ref() {
54+
unsafe { softbuffer::Surface::new(context, window) }
55+
.expect("Create softbuffer surface for window")
56+
} else {
57+
let context = unsafe { softbuffer::Context::new(window) }
58+
.expect("Create softbuffer context for window");
59+
unsafe { softbuffer::Surface::new(&context, window) }
60+
.expect("Create softbuffer surface for window")
61+
};
5362

5463
Surface {
5564
window,
56-
buffer: vec![0; width as usize * height as usize],
5765
clip_mask: tiny_skia::Mask::new(width, height)
5866
.expect("Create clip mask"),
59-
primitives: None,
67+
primitives: VecDeque::new(),
6068
background_color: Color::BLACK,
6169
}
6270
}
@@ -67,10 +75,9 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
6775
width: u32,
6876
height: u32,
6977
) {
70-
surface.buffer.resize((width * height) as usize, 0);
7178
surface.clip_mask =
7279
tiny_skia::Mask::new(width, height).expect("Create clip mask");
73-
surface.primitives = None;
80+
surface.primitives.clear();
7481
}
7582

7683
fn fetch_information(&self) -> Information {
@@ -121,8 +128,15 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
121128
}
122129
}
123130

124-
pub fn new<Theme>(settings: Settings) -> Compositor<Theme> {
131+
pub fn new<W: HasRawWindowHandle + HasRawDisplayHandle, Theme>(
132+
settings: Settings,
133+
compatible_window: Option<&W>,
134+
) -> Compositor<Theme> {
135+
#[allow(unsafe_code)]
136+
let context = compatible_window
137+
.and_then(|w| unsafe { softbuffer::Context::new(w) }.ok());
125138
Compositor {
139+
context,
126140
settings,
127141
_theme: PhantomData,
128142
}
@@ -139,48 +153,67 @@ pub fn present<T: AsRef<str>>(
139153
let physical_size = viewport.physical_size();
140154
let scale_factor = viewport.scale_factor() as f32;
141155

142-
let mut pixels = tiny_skia::PixmapMut::from_bytes(
143-
bytemuck::cast_slice_mut(&mut surface.buffer),
144-
physical_size.width,
145-
physical_size.height,
146-
)
147-
.expect("Create pixel map");
156+
surface
157+
.window
158+
.resize(
159+
NonZeroU32::new(physical_size.width).unwrap(),
160+
NonZeroU32::new(physical_size.height).unwrap(),
161+
)
162+
.unwrap();
163+
164+
// TODO Add variants to `SurfaceError`?
165+
let mut buffer = surface
166+
.window
167+
.buffer_mut()
168+
.map_err(|_| compositor::SurfaceError::Lost)?;
169+
170+
let age = buffer.age();
148171

149-
let damage = surface
150-
.primitives
151-
.as_deref()
172+
// Forget primatives for back buffers older than `age`
173+
// Or if this is a new buffer, keep at most two.
174+
let max = if age == 0 { 2 } else { age };
175+
while surface.primitives.len() as u8 > max {
176+
let _ = surface.primitives.pop_front();
177+
}
178+
179+
let last_primitives = if surface.primitives.len() as u8 == age {
180+
surface.primitives.pop_front()
181+
} else {
182+
None
183+
};
184+
185+
let damage = last_primitives
152186
.and_then(|last_primitives| {
153187
(surface.background_color == background_color)
154-
.then(|| damage::list(last_primitives, primitives))
188+
.then(|| damage::list(&last_primitives, primitives))
155189
})
156190
.unwrap_or_else(|| vec![Rectangle::with_size(viewport.logical_size())]);
157191

158-
if damage.is_empty() {
159-
return Ok(());
160-
}
161-
162-
surface.primitives = Some(primitives.to_vec());
192+
surface.primitives.push_back(primitives.to_vec());
163193
surface.background_color = background_color;
164194

165-
let damage = damage::group(damage, scale_factor, physical_size);
195+
if !damage.is_empty() {
196+
let damage = damage::group(damage, scale_factor, physical_size);
166197

167-
backend.draw(
168-
&mut pixels,
169-
&mut surface.clip_mask,
170-
primitives,
171-
viewport,
172-
&damage,
173-
background_color,
174-
overlay,
175-
);
198+
let mut pixels = tiny_skia::PixmapMut::from_bytes(
199+
bytemuck::cast_slice_mut(&mut buffer),
200+
physical_size.width,
201+
physical_size.height,
202+
)
203+
.expect("Create pixel map");
176204

177-
surface.window.set_buffer(
178-
&surface.buffer,
179-
physical_size.width as u16,
180-
physical_size.height as u16,
181-
);
205+
backend.draw(
206+
&mut pixels,
207+
&mut surface.clip_mask,
208+
primitives,
209+
viewport,
210+
&damage,
211+
background_color,
212+
overlay,
213+
);
214+
}
182215

183-
Ok(())
216+
buffer.present().map_err(|_| compositor::SurfaceError::Lost)
184217
}
185218

186219
pub fn screenshot<T: AsRef<str>>(

0 commit comments

Comments
 (0)