1
1
use crate :: { error:: unwrap, GraphicsContextImpl , SwBufError } ;
2
- use nix:: sys:: memfd:: { memfd_create, MemFdCreateFlag } ;
3
2
use raw_window_handle:: { WaylandDisplayHandle , WaylandWindowHandle } ;
4
- use std:: {
5
- ffi:: CStr ,
6
- fs:: File ,
7
- io:: Write ,
8
- os:: unix:: prelude:: { AsRawFd , FileExt , FromRawFd } ,
9
- } ;
10
3
use wayland_client:: {
11
4
backend:: { Backend , ObjectId } ,
12
5
globals:: { registry_queue_init, GlobalListContents } ,
13
- protocol:: { wl_buffer , wl_registry, wl_shm, wl_shm_pool , wl_surface} ,
6
+ protocol:: { wl_registry, wl_shm, wl_surface} ,
14
7
Connection , Dispatch , EventQueue , Proxy , QueueHandle ,
15
8
} ;
16
9
10
+ mod buffer;
11
+ use buffer:: WaylandBuffer ;
12
+
17
13
struct State ;
18
14
19
15
pub struct WaylandImpl {
20
16
event_queue : EventQueue < State > ,
21
17
qh : QueueHandle < State > ,
22
18
surface : wl_surface:: WlSurface ,
23
19
shm : wl_shm:: WlShm ,
24
- tempfile : File ,
25
- buffer : Option < WaylandBuffer > ,
26
- }
27
-
28
- struct WaylandBuffer {
29
- width : i32 ,
30
- height : i32 ,
31
- pool : wl_shm_pool:: WlShmPool ,
32
- buffer : wl_buffer:: WlBuffer ,
33
- }
34
-
35
- impl Drop for WaylandBuffer {
36
- fn drop ( & mut self ) {
37
- self . buffer . destroy ( ) ;
38
- self . pool . destroy ( ) ;
39
- }
20
+ buffers : Vec < WaylandBuffer > ,
40
21
}
41
22
42
23
impl WaylandImpl {
@@ -56,12 +37,6 @@ impl WaylandImpl {
56
37
globals. bind ( & qh, 1 ..=1 , ( ) ) ,
57
38
"Failed to instantiate Wayland Shm" ,
58
39
) ?;
59
- let name = CStr :: from_bytes_with_nul_unchecked ( "swbuf\0 " . as_bytes ( ) ) ;
60
- let tempfile_fd = unwrap (
61
- memfd_create ( name, MemFdCreateFlag :: MFD_CLOEXEC ) ,
62
- "Failed to create temporary file to store buffer." ,
63
- ) ?;
64
- let tempfile = File :: from_raw_fd ( tempfile_fd) ;
65
40
let surface_id = unwrap (
66
41
ObjectId :: from_ptr (
67
42
wl_surface:: WlSurface :: interface ( ) ,
@@ -78,58 +53,31 @@ impl WaylandImpl {
78
53
qh,
79
54
surface,
80
55
shm,
81
- tempfile,
82
- buffer : None ,
56
+ buffers : Vec :: new ( ) ,
83
57
} )
84
58
}
85
59
86
- fn ensure_buffer_size ( & mut self , width : i32 , height : i32 ) {
87
- if !self . check_buffer_size_equals ( width, height) {
88
- let pool =
89
- self . shm
90
- . create_pool ( self . tempfile . as_raw_fd ( ) , width * height * 4 , & self . qh , ( ) ) ;
91
- let buffer = pool. create_buffer (
92
- 0 ,
93
- width,
94
- height,
95
- width * 4 ,
96
- wayland_client:: protocol:: wl_shm:: Format :: Xrgb8888 ,
97
- & self . qh ,
98
- ( ) ,
99
- ) ;
100
- self . buffer = Some ( WaylandBuffer {
101
- width,
102
- height,
103
- pool,
104
- buffer,
105
- } ) ;
106
- }
107
- }
108
-
109
- fn check_buffer_size_equals ( & self , width : i32 , height : i32 ) -> bool {
110
- match & self . buffer {
111
- Some ( buffer) => buffer. width == width && buffer. height == height,
112
- None => false ,
60
+ // Allocate or reuse a buffer of the given size
61
+ fn buffer ( & mut self , width : i32 , height : i32 ) -> & WaylandBuffer {
62
+ if let Some ( idx) = self . buffers . iter ( ) . position ( |i| i. released ( ) ) {
63
+ self . buffers [ idx] . resize ( width, height) ;
64
+ & mut self . buffers [ idx]
65
+ } else {
66
+ self . buffers
67
+ . push ( WaylandBuffer :: new ( & self . shm , width, height, & self . qh ) ) ;
68
+ self . buffers . last ( ) . unwrap ( )
113
69
}
114
70
}
115
71
}
116
72
117
73
impl GraphicsContextImpl for WaylandImpl {
118
74
unsafe fn set_buffer ( & mut self , buffer : & [ u32 ] , width : u16 , height : u16 ) {
119
- self . ensure_buffer_size ( width as i32 , height as i32 ) ;
120
- let wayland_buffer = self . buffer . as_mut ( ) . unwrap ( ) ;
121
- self . tempfile . set_len ( buffer. len ( ) as u64 * 4 )
122
- . expect ( "Failed to truncate temporary file." ) ;
123
- self . tempfile
124
- . write_at (
125
- std:: slice:: from_raw_parts ( buffer. as_ptr ( ) as * const u8 , buffer. len ( ) * 4 ) ,
126
- 0 ,
127
- )
128
- . expect ( "Failed to write buffer to temporary file." ) ;
129
- self . tempfile
130
- . flush ( )
131
- . expect ( "Failed to flush buffer to temporary file." ) ;
132
- self . surface . attach ( Some ( & wayland_buffer. buffer ) , 0 , 0 ) ;
75
+ let _ = self . event_queue . dispatch_pending ( & mut State ) ;
76
+
77
+ let surface = self . surface . clone ( ) ;
78
+ let wayland_buffer = self . buffer ( width. into ( ) , height. into ( ) ) ;
79
+ wayland_buffer. write ( buffer) ;
80
+ wayland_buffer. attach ( & surface) ;
133
81
134
82
// FIXME: Proper damaging mechanism.
135
83
//
@@ -145,8 +93,8 @@ impl GraphicsContextImpl for WaylandImpl {
145
93
self . surface
146
94
. damage_buffer ( 0 , 0 , width as i32 , height as i32 ) ;
147
95
}
148
-
149
96
self . surface . commit ( ) ;
97
+
150
98
let _ = self . event_queue . flush ( ) ;
151
99
}
152
100
}
@@ -175,27 +123,3 @@ impl Dispatch<wl_shm::WlShm, ()> for State {
175
123
) {
176
124
}
177
125
}
178
-
179
- impl Dispatch < wl_shm_pool:: WlShmPool , ( ) > for State {
180
- fn event (
181
- _: & mut State ,
182
- _: & wl_shm_pool:: WlShmPool ,
183
- _: wl_shm_pool:: Event ,
184
- _: & ( ) ,
185
- _: & Connection ,
186
- _: & QueueHandle < State > ,
187
- ) {
188
- }
189
- }
190
-
191
- impl Dispatch < wl_buffer:: WlBuffer , ( ) > for State {
192
- fn event (
193
- _: & mut State ,
194
- _: & wl_buffer:: WlBuffer ,
195
- _: wl_buffer:: Event ,
196
- _: & ( ) ,
197
- _: & Connection ,
198
- _: & QueueHandle < State > ,
199
- ) {
200
- }
201
- }
0 commit comments