@@ -13,13 +13,9 @@ use indexmap::IndexMap;
1313use render:: gles:: GbmGlowBackend ;
1414use smithay:: {
1515 backend:: {
16- allocator:: {
17- dmabuf:: Dmabuf ,
18- gbm:: { GbmAllocator , GbmBufferFlags } ,
19- Buffer ,
20- } ,
21- drm:: { output:: DrmOutputRenderElements , DrmDeviceFd , DrmNode , NodeType } ,
22- egl:: { context:: ContextPriority , EGLContext , EGLDevice , EGLDisplay } ,
16+ allocator:: { dmabuf:: Dmabuf , format:: FormatSet , Buffer } ,
17+ drm:: { output:: DrmOutputRenderElements , DrmDeviceFd , DrmNode , NodeType , VrrSupport } ,
18+ egl:: { EGLContext , EGLDevice , EGLDisplay } ,
2319 input:: InputEvent ,
2420 libinput:: { LibinputInputBackend , LibinputSessionInterface } ,
2521 renderer:: { glow:: GlowRenderer , multigpu:: GpuManager } ,
@@ -47,7 +43,6 @@ use surface::GbmDrmOutput;
4743use tracing:: { error, info, trace, warn} ;
4844
4945use std:: {
50- borrow:: BorrowMut ,
5146 collections:: { HashMap , HashSet } ,
5247 path:: Path ,
5348 sync:: { atomic:: AtomicBool , Arc , RwLock } ,
@@ -59,11 +54,12 @@ pub mod render;
5954mod socket;
6055mod surface;
6156pub ( crate ) use surface:: Surface ;
57+ pub use surface:: Timings ;
6258
59+ pub use device:: MaybeLockedDevice ;
6360use device:: * ;
64- pub use surface:: Timings ;
6561
66- use super :: render:: { init_shaders , output_elements, CursorMode , CLEAR_COLOR } ;
62+ use super :: render:: { output_elements, CursorMode , CLEAR_COLOR } ;
6763
6864#[ derive( Debug ) ]
6965pub struct KmsState {
@@ -80,6 +76,13 @@ pub struct KmsState {
8076 pub syncobj_state : Option < DrmSyncobjState > ,
8177}
8278
79+ pub struct KmsGuard < ' a > {
80+ pub drm_devices : IndexMap < DrmNode , LockedDevice < ' a > > ,
81+ pub primary_node : Arc < RwLock < Option < DrmNode > > > ,
82+ api : & ' a mut GpuManager < GbmGlowBackend < DrmDeviceFd > > ,
83+ session : & ' a LibSeatSession ,
84+ }
85+
8386pub fn init_backend (
8487 dh : & DisplayHandle ,
8588 event_loop : & mut EventLoop < ' static , State > ,
@@ -515,47 +518,33 @@ impl KmsState {
515518 . copied ( )
516519 }
517520
521+ pub fn update_screen_filter ( & mut self , screen_filter : & ScreenFilter ) -> Result < ( ) > {
522+ for device in self . drm_devices . values_mut ( ) {
523+ for surface in device. surfaces . values_mut ( ) {
524+ surface. set_screen_filter ( screen_filter. clone ( ) ) ;
525+ }
526+ }
527+
528+ // We don't expect this to fail in a meaningful way.
529+ // The shader is already compiled at this point and we don't rely on any features,
530+ // that might not be available for any filters we currently expose.
531+ //
532+ // But we might conditionally fail here in the future.
533+ Ok ( ( ) )
534+ }
535+
518536 pub fn refresh_used_devices ( & mut self ) -> Result < ( ) > {
537+ let primary_node = self . primary_node . read ( ) . unwrap ( ) ;
519538 let mut used_devices = HashSet :: new ( ) ;
520539
521540 for device in self . drm_devices . values_mut ( ) {
522- if device. in_use ( self . primary_node . read ( ) . unwrap ( ) . as_ref ( ) ) {
523- if device. egl . is_none ( ) {
524- let egl = init_egl ( & device. gbm ) . context ( "Failed to create EGL context" ) ?;
525- let mut renderer = unsafe {
526- GlowRenderer :: new (
527- EGLContext :: new_shared_with_priority (
528- & egl. display ,
529- & egl. context ,
530- ContextPriority :: High ,
531- )
532- . context ( "Failed to create shared EGL context" ) ?,
533- )
534- . context ( "Failed to create GL renderer" ) ?
535- } ;
536- init_shaders ( renderer. borrow_mut ( ) ) . context ( "Failed to compile shaders" ) ?;
537- self . api . as_mut ( ) . add_node (
538- device. render_node ,
539- GbmAllocator :: new (
540- device. gbm . clone ( ) ,
541- // SCANOUT because stride bugs
542- GbmBufferFlags :: RENDERING | GbmBufferFlags :: SCANOUT ,
543- ) ,
544- renderer,
545- ) ;
546- device. egl = Some ( egl) ;
547- }
548- used_devices. insert ( device. render_node ) ;
549- } else {
550- if device. egl . is_some ( ) {
551- let _ = device. egl . take ( ) ;
552- self . api . as_mut ( ) . remove_node ( & device. render_node ) ;
553- }
541+ if device. update_egl ( primary_node. as_ref ( ) , self . api . as_mut ( ) ) ? {
542+ used_devices. insert ( device. render_node ( ) ) ;
554543 }
555544 }
556545
557546 // trigger re-evaluation... urgh
558- if let Some ( primary_node) = self . primary_node . read ( ) . unwrap ( ) . as_ref ( ) {
547+ if let Some ( primary_node) = primary_node. as_ref ( ) {
559548 let _ = self . api . single_renderer ( primary_node) ;
560549 }
561550
@@ -566,54 +555,92 @@ impl KmsState {
566555 . map ( |d| d. render_node )
567556 . collect :: < Vec < _ > > ( ) ;
568557 for node in all_devices {
569- let ( mut device, mut others) = self
558+ let ( mut device, others) = self
570559 . drm_devices
571560 . values_mut ( )
572561 . partition :: < Vec < _ > , _ > ( |d| d. render_node == node) ;
573- let device = & mut device[ 0 ] ;
562+ device[ 0 ] . update_surface_nodes ( & used_devices, others. iter ( ) . map ( |device| & * * device) ) ?;
563+ }
574564
575- for surface in device. surfaces . values_mut ( ) {
576- let known_nodes = surface. known_nodes ( ) . clone ( ) ;
577- for gone_device in known_nodes. difference ( & used_devices) {
578- surface. remove_node ( * gone_device) ;
579- }
580- for new_device in used_devices. difference ( & known_nodes) {
581- let ( render_node, egl, gbm) = if node == * new_device {
582- // we need to make sure to do partial borrows here, as device.surfaces is borrowed mutable
583- (
584- device. render_node ,
585- device. egl . as_ref ( ) . unwrap ( ) ,
586- device. gbm . clone ( ) ,
587- )
588- } else {
589- let device = others
590- . iter_mut ( )
591- . find ( |d| d. render_node == * new_device)
592- . unwrap ( ) ;
593- (
594- device. render_node ,
595- device. egl . as_ref ( ) . unwrap ( ) ,
596- device. gbm . clone ( ) ,
597- )
598- } ;
565+ Ok ( ( ) )
566+ }
599567
600- surface. add_node (
601- render_node,
602- GbmAllocator :: new ( gbm, GbmBufferFlags :: RENDERING | GbmBufferFlags :: SCANOUT ) ,
603- EGLContext :: new_shared_with_priority (
604- & egl. display ,
605- & egl. context ,
606- ContextPriority :: High ,
607- )
608- . context ( "Failed to create shared EGL context" ) ?,
609- ) ;
610- }
568+ pub fn lock_devices ( & mut self ) -> KmsGuard < ' _ > {
569+ KmsGuard {
570+ drm_devices : self
571+ . drm_devices
572+ . iter_mut ( )
573+ . map ( |( node, device) | ( * node, device. lock ( ) ) )
574+ . collect ( ) ,
575+ primary_node : self . primary_node . clone ( ) ,
576+ api : & mut self . api ,
577+ session : & self . session ,
578+ }
579+ }
580+ }
581+
582+ impl < ' a > KmsGuard < ' a > {
583+ pub fn schedule_render ( & mut self , output : & Output ) {
584+ for surface in self
585+ . drm_devices
586+ . values ( )
587+ . flat_map ( |d| d. surfaces . values ( ) )
588+ . filter ( |s| s. output == * output || s. output . mirroring ( ) . is_some_and ( |o| & o == output) )
589+ {
590+ surface. schedule_render ( ) ;
591+ }
592+ }
593+
594+ pub fn refresh_used_devices ( & mut self ) -> Result < ( ) > {
595+ let primary_node = self . primary_node . read ( ) . unwrap ( ) ;
596+ let mut used_devices = HashSet :: new ( ) ;
597+
598+ for device in self . drm_devices . values_mut ( ) {
599+ if device. update_egl ( primary_node. as_ref ( ) , self . api . as_mut ( ) ) ? {
600+ used_devices. insert ( device. render_node ( ) ) ;
611601 }
612602 }
613603
604+ // trigger re-evaluation... urgh
605+ if let Some ( primary_node) = primary_node. as_ref ( ) {
606+ let _ = self . api . single_renderer ( primary_node) ;
607+ }
608+
609+ // I hate this. I want partial borrows of hashmap values
610+ let all_devices = self
611+ . drm_devices
612+ . values ( )
613+ . map ( |d| d. render_node )
614+ . collect :: < Vec < _ > > ( ) ;
615+ for node in all_devices {
616+ let ( mut device, others) = self
617+ . drm_devices
618+ . values_mut ( )
619+ . partition :: < Vec < _ > , _ > ( |d| d. render_node == node) ;
620+ device[ 0 ] . update_surface_nodes ( & used_devices, others. iter ( ) . map ( |device| & * * device) ) ?;
621+ }
622+
614623 Ok ( ( ) )
615624 }
616625
626+ pub fn all_outputs ( & self ) -> Vec < Output > {
627+ self . drm_devices
628+ . values ( )
629+ . flat_map ( |device| {
630+ device
631+ . outputs
632+ . iter ( )
633+ . filter ( |( conn, _) | {
634+ !device
635+ . leased_connectors
636+ . iter ( )
637+ . any ( |( leased_conn, _) | * conn == leased_conn)
638+ } )
639+ . map ( |( _, output) | output. clone ( ) )
640+ } )
641+ . collect ( )
642+ }
643+
617644 pub fn apply_config_for_outputs (
618645 & mut self ,
619646 test_only : bool ,
@@ -622,9 +649,9 @@ impl KmsState {
622649 shell : Arc < parking_lot:: RwLock < Shell > > ,
623650 startup_done : Arc < AtomicBool > ,
624651 clock : & Clock < Monotonic > ,
625- ) -> Result < Vec < Output > , anyhow:: Error > {
652+ ) -> Result < ( ) , anyhow:: Error > {
626653 if !self . session . is_active ( ) {
627- return Ok ( Vec :: new ( ) ) ;
654+ return Ok ( ( ) ) ;
628655 }
629656
630657 for device in self . drm_devices . values_mut ( ) {
@@ -771,7 +798,7 @@ impl KmsState {
771798 for ( crtc, surface) in device. surfaces . iter_mut ( ) {
772799 let output_config = surface. output . config ( ) ;
773800
774- let drm = & mut device. drm . lock ( ) ;
801+ let drm = & mut device. drm ;
775802 let conn = surface. connector ;
776803 let conn_info = drm. device ( ) . get_connector ( conn, false ) ?;
777804 let mode = conn_info
@@ -861,34 +888,61 @@ impl KmsState {
861888 let vrr = output_config. vrr ;
862889 std:: mem:: drop ( output_config) ;
863890
864- match surface. resume ( compositor) {
865- Ok ( _) => {
866- surface. output . set_adaptive_sync_support (
867- surface. adaptive_sync_support ( ) . ok ( ) ,
868- ) ;
869- if surface. use_adaptive_sync ( vrr) ? {
870- surface. output . set_adaptive_sync ( vrr) ;
871- } else {
872- surface. output . config_mut ( ) . vrr = AdaptiveSync :: Disabled ;
873- surface. output . set_adaptive_sync ( AdaptiveSync :: Disabled ) ;
874- }
875- }
876- Err ( err) => {
877- surface. output . config_mut ( ) . enabled = OutputState :: Disabled ;
878- return Err ( err) . context ( "Failed to create surface" ) ;
891+ let compositor_ref = drm. compositors ( ) . get ( crtc) . unwrap ( ) . lock ( ) . unwrap ( ) ;
892+ let vrr_support = compositor_ref
893+ . vrr_supported (
894+ compositor_ref
895+ . pending_connectors ( )
896+ . into_iter ( )
897+ . next ( )
898+ . unwrap ( ) ,
899+ )
900+ . ok ( ) ;
901+ surface. resume (
902+ compositor,
903+ compositor_ref. surface ( ) . plane_info ( ) . formats . clone ( ) ,
904+ compositor_ref
905+ . surface ( )
906+ . planes ( )
907+ . overlay
908+ . iter ( )
909+ . flat_map ( |p| p. formats . iter ( ) . cloned ( ) )
910+ . collect :: < FormatSet > ( ) ,
911+ ) ;
912+
913+ surface. output . set_adaptive_sync_support ( vrr_support) ;
914+ if match vrr_support {
915+ Some ( VrrSupport :: RequiresModeset ) if vrr == AdaptiveSync :: Enabled => {
916+ false
879917 }
918+ Some ( VrrSupport :: NotSupported ) => false ,
919+ _ => true ,
920+ } {
921+ surface. use_adaptive_sync ( vrr) ;
922+ surface. output . set_adaptive_sync ( vrr) ;
923+ } else {
924+ surface. use_adaptive_sync ( AdaptiveSync :: Disabled ) ;
925+ surface. output . config_mut ( ) . vrr = AdaptiveSync :: Disabled ;
926+ surface. output . set_adaptive_sync ( AdaptiveSync :: Disabled ) ;
880927 }
881928 } else {
882929 let vrr = output_config. vrr ;
883930 std:: mem:: drop ( output_config) ;
884931 if vrr != surface. output . adaptive_sync ( ) {
885- if surface. use_adaptive_sync ( vrr) ? {
886- surface. output . set_adaptive_sync ( vrr) ;
887- } else if vrr != AdaptiveSync :: Disabled {
932+ if match surface. output . adaptive_sync_support ( ) {
933+ Some ( VrrSupport :: RequiresModeset )
934+ if vrr == AdaptiveSync :: Enabled =>
935+ {
936+ true
937+ }
938+ Some ( VrrSupport :: NotSupported ) => true ,
939+ _ => false ,
940+ } {
888941 anyhow:: bail!( "Requested VRR mode unsupported" ) ;
889- } else {
890- surface. output . set_adaptive_sync ( AdaptiveSync :: Disabled ) ;
891942 }
943+
944+ surface. use_adaptive_sync ( vrr) ;
945+ surface. output . set_adaptive_sync ( vrr) ;
892946 }
893947
894948 let mut renderer = self
@@ -956,7 +1010,6 @@ impl KmsState {
9561010
9571011 if let Err ( err) = device
9581012 . drm
959- . lock ( )
9601013 . try_to_restore_modifiers ( & mut renderer, & elements)
9611014 {
9621015 warn ! ( ?err, "Failed to restore modifiers" ) ;
@@ -988,21 +1041,6 @@ impl KmsState {
9881041 }
9891042 }
9901043
991- Ok ( all_outputs)
992- }
993-
994- pub fn update_screen_filter ( & mut self , screen_filter : & ScreenFilter ) -> Result < ( ) > {
995- for device in self . drm_devices . values_mut ( ) {
996- for surface in device. surfaces . values_mut ( ) {
997- surface. set_screen_filter ( screen_filter. clone ( ) ) ;
998- }
999- }
1000-
1001- // We don't expect this to fail in a meaningful way.
1002- // The shader is already compiled at this point and we don't rely on any features,
1003- // that might not be available for any filters we currently expose.
1004- //
1005- // But we might conditionally fail here in the future.
10061044 Ok ( ( ) )
10071045 }
10081046}
0 commit comments