@@ -5,18 +5,21 @@ use crate::graphics::{Error, Viewport};
55use crate :: { Backend , Primitive , Renderer , Settings } ;
66
77use raw_window_handle:: { HasRawDisplayHandle , HasRawWindowHandle } ;
8+ use std:: collections:: VecDeque ;
89use std:: marker:: PhantomData ;
10+ use std:: num:: NonZeroU32 ;
911
1012pub struct Compositor < Theme > {
13+ context : Option < softbuffer:: Context > ,
1114 settings : Settings ,
1215 _theme : PhantomData < Theme > ,
1316}
1417
1518pub 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
186219pub fn screenshot < T : AsRef < str > > (
0 commit comments