11use crossbeam_channel:: { Receiver , Sender , TrySendError , bounded} ;
22use gtk:: { gdk:: MemoryFormat , glib:: Bytes } ;
33use krun_display:: {
4- DisplayBackendBasicFramebuffer , DisplayBackendError , DisplayBackendNew , MAX_DISPLAYS , Rect ,
5- ResourceFormat ,
4+ DisplayBackendBasicFramebuffer , DisplayBackendDmabuf , DisplayBackendError , DisplayBackendNew ,
5+ DmabufExport , MAX_DISPLAYS , Rect , ResourceFormat ,
66} ;
77use log:: error;
88use std:: mem;
@@ -21,6 +21,13 @@ const _: () = {
2121
2222#[ derive( Debug , Clone ) ]
2323pub enum DisplayEvent {
24+ ImportDmabuf {
25+ dmabuf_id : u32 ,
26+ dmabuf_export : DmabufExport ,
27+ } ,
28+ UnrefDmabuf {
29+ dmabuf_id : u32 ,
30+ } ,
2431 ConfigureScanout {
2532 scanout_id : u32 ,
2633 display_width : u32 ,
@@ -29,6 +36,13 @@ pub enum DisplayEvent {
2936 height : u32 ,
3037 format : MemoryFormat ,
3138 } ,
39+ ConfigureScanoutDmabuf {
40+ scanout_id : u32 ,
41+ display_width : u32 ,
42+ display_height : u32 ,
43+ dmabuf_id : u32 ,
44+ src_rect : Option < Rect > ,
45+ } ,
3246 DisableScanout {
3347 scanout_id : u32 ,
3448 } ,
@@ -37,24 +51,29 @@ pub enum DisplayEvent {
3751 buffer : Bytes ,
3852 rect : Option < Rect > ,
3953 } ,
54+ UpdateScanoutDmabuf {
55+ scanout_id : u32 ,
56+ rect : Option < Rect > ,
57+ } ,
4058}
4159
4260// Implements libkrun traits (callbacks) to provide a display implementation, by forwarding the
4361// events to the `DisplayWorker`
4462pub struct GtkDisplayBackend {
4563 channel : PollableChannelSender < DisplayEvent > ,
4664 scanouts : [ Option < Scanout > ; MAX_DISPLAYS ] ,
65+ next_dmabuf_id : u32 ,
4766}
4867
4968impl DisplayBackendNew < PollableChannelSender < DisplayEvent > > for GtkDisplayBackend {
50- fn new ( channel : Option < & PollableChannelSender < DisplayEvent > > ) -> Self {
51- let channel = channel
52- . expect ( "The channel should have been set by GtkDisplayBackend::into_display_backend" )
53- . clone ( ) ;
69+ fn new ( userdata : Option < & PollableChannelSender < DisplayEvent > > ) -> Self {
70+ let channel = userdata
71+ . expect ( "The userdata should have been set by GtkDisplayBackend::into_display_backend" ) ;
5472
5573 Self {
56- channel,
74+ channel : channel . clone ( ) ,
5775 scanouts : Default :: default ( ) ,
76+ next_dmabuf_id : 1 ,
5877 }
5978 }
6079}
@@ -89,6 +108,7 @@ impl DisplayBackendBasicFramebuffer for GtkDisplayBackend {
89108 buffer_rx,
90109 buffer_tx,
91110 current_buffer : Vec :: new ( ) ,
111+ has_dmabuf : false ,
92112 } ) ;
93113 }
94114
@@ -157,6 +177,75 @@ impl DisplayBackendBasicFramebuffer for GtkDisplayBackend {
157177 }
158178}
159179
180+ impl DisplayBackendDmabuf for GtkDisplayBackend {
181+ fn import_dmabuf ( & mut self , dmabuf_export : & DmabufExport ) -> Result < u32 , DisplayBackendError > {
182+ let dmabuf_id = self . next_dmabuf_id ;
183+ self . next_dmabuf_id += 1 ;
184+
185+ self . channel
186+ . send ( DisplayEvent :: ImportDmabuf {
187+ dmabuf_id,
188+ dmabuf_export : * dmabuf_export,
189+ } )
190+ . unwrap ( ) ;
191+
192+ Ok ( dmabuf_id)
193+ }
194+
195+ fn unref_dmabuf ( & mut self , dmabuf_id : u32 ) -> Result < ( ) , DisplayBackendError > {
196+ self . channel
197+ . send ( DisplayEvent :: UnrefDmabuf { dmabuf_id } )
198+ . unwrap ( ) ;
199+
200+ Ok ( ( ) )
201+ }
202+
203+ fn configure_scanout_dmabuf (
204+ & mut self ,
205+ scanout_id : u32 ,
206+ display_width : u32 ,
207+ display_height : u32 ,
208+ dmabuf_id : u32 ,
209+ src_rect : Option < & Rect > ,
210+ ) -> Result < ( ) , DisplayBackendError > {
211+ let Some ( scanout) = & mut self . scanouts [ scanout_id as usize ] else {
212+ return Err ( DisplayBackendError :: InvalidScanoutId ) ;
213+ } ;
214+
215+ scanout. has_dmabuf = true ;
216+
217+ self . channel
218+ . send ( DisplayEvent :: ConfigureScanoutDmabuf {
219+ scanout_id,
220+ display_width,
221+ display_height,
222+ dmabuf_id,
223+ src_rect : src_rect. copied ( ) ,
224+ } )
225+ . unwrap ( ) ;
226+ Ok ( ( ) )
227+ }
228+
229+ fn present_dmabuf (
230+ & mut self ,
231+ scanout_id : u32 ,
232+ rect : Option < & Rect > ,
233+ ) -> Result < ( ) , DisplayBackendError > {
234+ if self . scanouts [ scanout_id as usize ]
235+ . as_ref ( )
236+ . is_none_or ( |scanout| !scanout. has_dmabuf )
237+ {
238+ return Err ( DisplayBackendError :: InvalidScanoutId ) ;
239+ } ;
240+
241+ let rect = rect. copied ( ) ;
242+ self . channel
243+ . send ( DisplayEvent :: UpdateScanoutDmabuf { scanout_id, rect } )
244+ . unwrap ( ) ;
245+ Ok ( ( ) )
246+ }
247+ }
248+
160249fn resource_format_into_gdk ( format : ResourceFormat ) -> MemoryFormat {
161250 match format {
162251 ResourceFormat :: BGRA => MemoryFormat :: B8g8r8a8 ,
@@ -175,6 +264,7 @@ struct Scanout {
175264 buffer_rx : Receiver < Vec < u8 > > ,
176265 required_buffer_size : usize ,
177266 current_buffer : Vec < u8 > ,
267+ has_dmabuf : bool ,
178268}
179269
180270impl Scanout {
0 commit comments