77 transaction:: { DrmConnectorState , DrmPlaneState } ,
88 video:: { MetalConnector , MetalCrtc , MetalHardwareCursorChange , MetalPlane } ,
99 } ,
10- cmm:: cmm_description:: ColorDescription ,
10+ cmm:: { cmm_description:: ColorDescription , cmm_render_intent :: RenderIntent } ,
1111 gfx_api:: {
1212 AcquireSync , BufferResv , DirectScanoutPosition , GfxRenderPass , GfxTexture , LazyTexture ,
1313 ReleaseSync , SyncFile , TextureUse , create_render_pass,
2727 } ,
2828 } ,
2929 arrayvec:: ArrayVec ,
30+ jay_proc:: jay_hash,
3031 std:: rc:: { Rc , Weak } ,
3132 uapi:: { OwnedFd , c} ,
3233} ;
@@ -44,24 +45,44 @@ pub struct DirectScanoutCache {
4445 fb : Option < Rc < DrmFramebuffer > > ,
4546}
4647
48+ #[ jay_hash]
49+ #[ derive( Copy , Clone , Debug ) ]
50+ pub struct DirectScanoutKey {
51+ dma_buf_id : DmaBufId ,
52+ has_cursor_plane : bool ,
53+ }
54+
55+ #[ derive( Debug ) ]
56+ struct DirectScanoutData {
57+ fb_cd : Rc < ColorDescription > ,
58+ fb_intent : RenderIntent ,
59+ key : DirectScanoutKey ,
60+ }
61+
4762#[ derive( Debug ) ]
48- pub struct DirectScanoutData {
63+ struct DirectScanoutDataCore {
4964 tex : Rc < dyn GfxTexture > ,
5065 tex_resv : Option < Rc < dyn BufferResv > > ,
5166 acquire_sync : AcquireSync ,
5267 release_sync : ReleaseSync ,
5368 _fb_resv : Option < Rc < dyn BufferResv > > ,
5469 lazy : Option < Rc < dyn LazyTexture > > ,
5570 fb : Rc < DrmFramebuffer > ,
56- dma_buf_id : DmaBufId ,
5771 position : DirectScanoutPosition ,
5872}
5973
60- pub struct PresentFb {
74+ struct PresentFb {
75+ fb_intent : RenderIntent ,
76+ copy : RenderBufferCopy ,
77+ direct_scanout_key : Option < DirectScanoutKey > ,
78+ core : PresentFbCore ,
79+ }
80+
81+ pub struct PresentFbCore {
6182 fb : Rc < DrmFramebuffer > ,
83+ fb_cd : Rc < ColorDescription > ,
6284 tex : Rc < dyn GfxTexture > ,
63- direct_scanout_data : Option < DirectScanoutData > ,
64- copy : RenderBufferCopy ,
85+ direct_scanout_data : Option < DirectScanoutDataCore > ,
6586 pub locked : bool ,
6687}
6788
@@ -218,10 +239,10 @@ impl MetalConnector {
218239 }
219240
220241 let mut present_fb = None ;
221- let mut direct_scanout_id = None ;
242+ let mut direct_scanout_key = None ;
222243 if let Some ( latched) = & latched {
223244 let fb = self . prepare_present_fb ( & cd, blend_cd, buffer, & plane, latched, true ) ?;
224- direct_scanout_id = fb. direct_scanout_data . as_ref ( ) . map ( |d| d . dma_buf_id ) ;
245+ direct_scanout_key = fb. direct_scanout_key ;
225246 present_fb = Some ( fb) ;
226247 }
227248 self . await_present_fb ( present_fb. as_mut ( ) , PresentFbWait :: Render )
@@ -231,7 +252,7 @@ impl MetalConnector {
231252 // could interfere with scanout. However, perform_screencopies just uses the
232253 // current PresentFb if present_fb is None, potentially mutating the fb that is
233254 // currently being scanned out, which would render such a wait absurd.
234- self . perform_screencopies ( & present_fb, & node, & cd ) ;
255+ self . perform_screencopies ( & present_fb, & node) ;
235256 if let Some ( sync) = self . cursor_sync . take ( ) {
236257 sync. signaled ( & self . state . ring , "cursor" ) . await ;
237258 }
@@ -248,7 +269,7 @@ impl MetalConnector {
248269 & mut connector_drm_state,
249270 ) ;
250271 if res. is_err ( )
251- && let Some ( dsd_id ) = direct_scanout_id
272+ && let Some ( dsk ) = direct_scanout_key
252273 {
253274 let fb = self . prepare_present_fb (
254275 & cd,
@@ -271,16 +292,7 @@ impl MetalConnector {
271292 & mut connector_drm_state,
272293 ) ;
273294 if res. is_ok ( ) {
274- let mut cache = self . scanout_buffers . borrow_mut ( ) ;
275- if let Some ( buffer) = cache. remove ( & dsd_id) {
276- cache. insert (
277- dsd_id,
278- DirectScanoutCache {
279- dmabuf : buffer. dmabuf ,
280- fb : None ,
281- } ,
282- ) ;
283- }
295+ self . scanout_impossible_cache . insert ( dsk, ( ) ) ;
284296 }
285297 }
286298 let reset_damage = || {
@@ -307,15 +319,17 @@ impl MetalConnector {
307319 * plane. plane . drm_state . borrow_mut ( ) = plane. state ;
308320 }
309321 if let Some ( fb) = present_fb {
322+ self . fb_color_description . set ( fb. core . fb_cd . clone ( ) ) ;
323+ self . fb_render_intent . set ( fb. fb_intent ) ;
310324 self . presentation_is_zero_copy
311- . set ( fb. direct_scanout_data . is_some ( ) ) ;
312- if fb. direct_scanout_data . is_none ( ) {
325+ . set ( fb. core . direct_scanout_data . is_some ( ) ) ;
326+ if fb. core . direct_scanout_data . is_none ( ) {
313327 buffer. damage_queue . clear ( ) ;
314328 } else {
315329 reset_damage ( ) ;
316330 }
317- buffer. locked . set ( fb. locked ) ;
318- self . next_framebuffer . set ( Some ( fb) ) ;
331+ buffer. locked . set ( fb. core . locked ) ;
332+ self . next_framebuffer . set ( Some ( fb. core ) ) ;
319333 }
320334 if let Some ( programming) = cursor_programming
321335 && let CursorProgrammingType :: Enable { swap : true , .. } = & programming. ty
@@ -372,7 +386,7 @@ impl MetalConnector {
372386 let mut connector_state = connector_drm_state. clone ( ) ;
373387 if let Some ( fb) = new_fb {
374388 let ( crtc_x, crtc_y, crtc_w, crtc_h, src_width, src_height) =
375- match & fb. direct_scanout_data {
389+ match & fb. core . direct_scanout_data {
376390 None => {
377391 let plane_w = plane. mode_w . get ( ) ;
378392 let plane_h = plane. mode_h . get ( ) ;
@@ -391,11 +405,11 @@ impl MetalConnector {
391405 }
392406 } ;
393407 changes. change_object ( plane. id , |c| {
394- c. change ( drm_state. fb_id . id , fb. fb . id ( ) ) ;
395- drm_state. fb_id . value = fb. fb . id ( ) ;
396- connector_state. fb = fb. fb . id ( ) ;
397- connector_state. locked = fb. locked ;
398- if fb. direct_scanout_data . is_none ( ) {
408+ c. change ( drm_state. fb_id . id , fb. core . fb . id ( ) ) ;
409+ drm_state. fb_id . value = fb. core . fb . id ( ) ;
410+ connector_state. fb = fb. core . fb . id ( ) ;
411+ connector_state. locked = fb. core . locked ;
412+ if fb. core . direct_scanout_data . is_none ( ) {
399413 connector_state. fb_idx += 1 ;
400414 }
401415 macro_rules! change {
@@ -456,7 +470,7 @@ impl MetalConnector {
456470 change ! ( src_y, 0 ) ;
457471 change ! ( src_w, ( * width as u32 ) << 16 ) ;
458472 change ! ( src_h, ( * height as u32 ) << 16 ) ;
459- if !self . dev . is_nvidia
473+ if !self . dev . vendor . is_nvidia
460474 && let Some ( sf) = self . backend . signaled_sync_file . get ( )
461475 {
462476 c. change ( plane. in_fence_fd , sf. 0 . raw ( ) as u64 ) ;
@@ -489,7 +503,7 @@ impl MetalConnector {
489503 }
490504 }
491505 self . presentation_is_sync . set ( true ) ;
492- if !self . dev . is_nvidia {
506+ if !self . dev . vendor . is_nvidia {
493507 if new_fb. is_some ( )
494508 && let Some ( sf) = self . backend . signaled_sync_file . get ( )
495509 {
@@ -636,7 +650,7 @@ impl MetalConnector {
636650 plane : & Rc < MetalPlane > ,
637651 blend_cd : & Rc < ColorDescription > ,
638652 cd : & Rc < ColorDescription > ,
639- ) -> Option < DirectScanoutData > {
653+ ) -> Option < ( DirectScanoutData , DirectScanoutDataCore ) > {
640654 let ( ct, position) = pass. prepare_direct_scanout (
641655 plane. mode_w . get ( ) ,
642656 plane. mode_h . get ( ) ,
@@ -682,19 +696,46 @@ impl MetalConnector {
682696 // Shm buffers cannot be scanned out.
683697 return None ;
684698 } ;
685- let mut cache = self . scanout_buffers . borrow_mut ( ) ;
686- if let Some ( buffer) = cache. get ( & dmabuf. id ) {
687- return buffer. fb . as_ref ( ) . map ( |fb| DirectScanoutData {
699+ let key = DirectScanoutKey {
700+ dma_buf_id : dmabuf. id ,
701+ has_cursor_plane : self . cursor_enabled . get ( ) ,
702+ } ;
703+ if let Some ( v) = self . scanout_impossible_cache . get ( & key) {
704+ v. mark_used ( ) ;
705+ return None ;
706+ }
707+ let res = self . prepare_direct_scanout3 ( plane, dmabuf) ;
708+ if res. is_none ( ) {
709+ self . scanout_impossible_cache . insert ( key, ( ) ) ;
710+ }
711+ res. map ( |fb| {
712+ let data = DirectScanoutData {
713+ fb_cd : ct. cd . clone ( ) ,
714+ fb_intent : ct. render_intent ,
715+ key,
716+ } ;
717+ let core = DirectScanoutDataCore {
688718 tex : ct. tex . clone ( ) ,
689719 tex_resv : ct. buffer_resv . clone ( ) ,
690720 acquire_sync : ct. acquire_sync . clone ( ) ,
691721 release_sync,
692722 _fb_resv : fb_resv,
693723 lazy : ct. lazy . clone ( ) ,
694- fb : fb. clone ( ) ,
695- dma_buf_id : dmabuf. id ,
724+ fb,
696725 position,
697- } ) ;
726+ } ;
727+ ( data, core)
728+ } )
729+ }
730+
731+ fn prepare_direct_scanout3 (
732+ & self ,
733+ plane : & Rc < MetalPlane > ,
734+ dmabuf : & Rc < DmaBuf > ,
735+ ) -> Option < Rc < DrmFramebuffer > > {
736+ let mut cache = self . scanout_buffers . borrow_mut ( ) ;
737+ if let Some ( buffer) = cache. get ( & dmabuf. id ) {
738+ return buffer. fb . clone ( ) ;
698739 }
699740 let format = ' format: {
700741 if let Some ( f) = plane. formats . get ( & dmabuf. format . drm ) {
@@ -711,18 +752,8 @@ impl MetalConnector {
711752 if !format. modifiers . contains ( & dmabuf. modifier ) {
712753 return None ;
713754 }
714- let data = match self . dev . master . add_fb ( dmabuf, Some ( format. format ) ) {
715- Ok ( fb) => Some ( DirectScanoutData {
716- tex : ct. tex . clone ( ) ,
717- tex_resv : ct. buffer_resv . clone ( ) ,
718- acquire_sync : ct. acquire_sync . clone ( ) ,
719- release_sync,
720- _fb_resv : fb_resv,
721- lazy : ct. lazy . clone ( ) ,
722- fb : Rc :: new ( fb) ,
723- dma_buf_id : dmabuf. id ,
724- position,
725- } ) ,
755+ let fb = match self . dev . master . add_fb ( dmabuf, Some ( format. format ) ) {
756+ Ok ( fb) => Some ( Rc :: new ( fb) ) ,
726757 Err ( e) => {
727758 log:: debug!(
728759 "Could not import dmabuf for direct scanout: {}" ,
@@ -735,10 +766,10 @@ impl MetalConnector {
735766 dmabuf. id ,
736767 DirectScanoutCache {
737768 dmabuf : Rc :: downgrade ( dmabuf) ,
738- fb : data . as_ref ( ) . map ( |dsd| dsd . fb . clone ( ) ) ,
769+ fb : fb. clone ( ) ,
739770 } ,
740771 ) ;
741- data
772+ fb
742773 }
743774
744775 fn prepare_present_fb (
@@ -766,9 +797,30 @@ impl MetalConnector {
766797 }
767798 let copy;
768799 let fb;
800+ let fb_cd;
801+ let fb_intent;
769802 let tex;
770- match & direct_scanout_data {
771- None => {
803+ let direct_scanout_key;
804+ let ( dsd, mut dsd_core) = direct_scanout_data. unzip ( ) ;
805+ match ( dsd, & mut dsd_core) {
806+ ( Some ( dsd) , Some ( core) ) => {
807+ if let Some ( lazy) = & core. lazy {
808+ lazy. record_use ( TextureUse :: Scanout ) ;
809+ }
810+ let sync = match & core. acquire_sync {
811+ AcquireSync :: None => None ,
812+ AcquireSync :: Implicit => None ,
813+ AcquireSync :: FdSync ( sync) => Some ( sync. clone ( ) ) ,
814+ AcquireSync :: Unnecessary => None ,
815+ } ;
816+ copy = RenderBufferCopy :: for_both ( sync) ;
817+ fb = core. fb . clone ( ) ;
818+ fb_cd = dsd. fb_cd ;
819+ fb_intent = dsd. fb_intent ;
820+ direct_scanout_key = Some ( dsd. key ) ;
821+ tex = core. tex . clone ( ) ;
822+ }
823+ _ => {
772824 let sf = buffer
773825 . render
774826 . fb
@@ -786,41 +838,30 @@ impl MetalConnector {
786838 . copy_to_dev ( cd, Some ( & latched. damage ) , sf)
787839 . map_err ( MetalError :: CopyToDev ) ?;
788840 fb = buffer. drm . clone ( ) ;
841+ fb_cd = cd. clone ( ) ;
842+ fb_intent = RenderIntent :: Perceptual ;
843+ direct_scanout_key = None ;
789844 tex = buffer. render . tex . clone ( ) ;
790845 }
791- Some ( dsd) => {
792- if let Some ( lazy) = & dsd. lazy {
793- lazy. record_use ( TextureUse :: Scanout ) ;
794- }
795- let sync = match & dsd. acquire_sync {
796- AcquireSync :: None => None ,
797- AcquireSync :: Implicit => None ,
798- AcquireSync :: FdSync ( sync) => Some ( sync. clone ( ) ) ,
799- AcquireSync :: Unnecessary => None ,
800- } ;
801- copy = RenderBufferCopy :: for_both ( sync) ;
802- fb = dsd. fb . clone ( ) ;
803- tex = dsd. tex . clone ( ) ;
804- }
805846 } ;
806847 Ok ( PresentFb {
807- fb,
808- tex,
809- direct_scanout_data,
848+ fb_intent,
810849 copy,
811- locked : latched. locked ,
850+ direct_scanout_key,
851+ core : PresentFbCore {
852+ fb,
853+ fb_cd,
854+ tex,
855+ direct_scanout_data : dsd_core,
856+ locked : latched. locked ,
857+ } ,
812858 } )
813859 }
814860
815- fn perform_screencopies (
816- & self ,
817- new_fb : & Option < PresentFb > ,
818- output : & OutputNode ,
819- cd : & Rc < ColorDescription > ,
820- ) {
861+ fn perform_screencopies ( & self , new_fb : & Option < PresentFb > , output : & OutputNode ) {
821862 let active_fb;
822863 let fb = match & new_fb {
823- Some ( f) => f ,
864+ Some ( f) => & f . core ,
824865 None => {
825866 active_fb = self . active_framebuffer . borrow ( ) ;
826867 match & * active_fb {
@@ -834,7 +875,7 @@ impl MetalConnector {
834875 None => {
835876 output. perform_screencopies (
836877 & fb. tex ,
837- cd ,
878+ & fb . fb_cd ,
838879 None ,
839880 None ,
840881 & AcquireSync :: Unnecessary ,
@@ -848,7 +889,7 @@ impl MetalConnector {
848889 Some ( dsd) => {
849890 output. perform_screencopies (
850891 & dsd. tex ,
851- cd ,
892+ & fb . fb_cd ,
852893 dsd. tex_resv . as_ref ( ) ,
853894 dsd. lazy . as_ref ( ) ,
854895 & dsd. acquire_sync ,
0 commit comments