1
+ use alloc:: sync:: Arc ;
2
+ use core:: { ffi, ptr} ;
3
+
4
+ use once_cell:: sync:: Lazy ;
1
5
use windows:: Win32 :: { Foundation :: HWND , Graphics :: DirectComposition } ;
6
+ use windows_core:: Interface ;
7
+
8
+ use super :: DynLib ;
9
+
10
+ // Lazy-loaded DirectComposition library
11
+ #[ derive( Debug ) ]
12
+ pub ( crate ) struct DCompLib {
13
+ lib : Lazy < Result < DynLib , crate :: SurfaceError > > ,
14
+ }
15
+
16
+ impl DCompLib {
17
+ pub ( crate ) fn new ( ) -> Self {
18
+ Self {
19
+ lib : Lazy :: new ( || unsafe {
20
+ DynLib :: new ( "dcomp.dll" ) . map_err ( |err| {
21
+ log:: error!( "Error loading dcomp.dll: {err}" ) ;
22
+ crate :: SurfaceError :: Other ( "Error loading dcomp.dll" )
23
+ } )
24
+ } ) ,
25
+ }
26
+ }
27
+
28
+ fn get_lib ( & self ) -> Result < & DynLib , crate :: SurfaceError > {
29
+ match self . lib . as_ref ( ) {
30
+ Ok ( lib) => Ok ( lib) ,
31
+ Err ( err) => Err ( err. clone ( ) ) ,
32
+ }
33
+ }
34
+
35
+ pub ( crate ) fn create_device (
36
+ & self ,
37
+ ) -> Result < DirectComposition :: IDCompositionDevice , crate :: SurfaceError > {
38
+ let lib = self . get_lib ( ) ?;
39
+
40
+ // Calls windows::Win32::Graphics::DirectComposition::DCompositionCreateDevice2 on dcomp.dll
41
+ type Fun = extern "system" fn (
42
+ pdxdevice : * mut ffi:: c_void ,
43
+ riid : * const windows_core:: GUID ,
44
+ ppdcompdevice : * mut * mut ffi:: c_void ,
45
+ ) -> windows_core:: HRESULT ;
46
+ let func: libloading:: Symbol < Fun > =
47
+ unsafe { lib. get ( c"DCompositionCreateDevice2" . to_bytes ( ) ) } ?;
48
+
49
+ let mut res: Option < DirectComposition :: IDCompositionDevice > = None ;
50
+
51
+ ( func) (
52
+ ptr:: null_mut ( ) ,
53
+ & DirectComposition :: IDCompositionDevice :: IID ,
54
+ <* mut _ >:: cast ( & mut res) ,
55
+ )
56
+ . map ( || res. unwrap ( ) )
57
+ . map_err ( |err| {
58
+ log:: error!( "DirectComposition::DCompositionCreateDevice2 failed: {err}" ) ;
59
+ crate :: SurfaceError :: Other ( "DirectComposition::DCompositionCreateDevice2" )
60
+ } )
61
+ }
62
+ }
2
63
3
64
#[ derive( Default ) ]
4
65
pub struct DCompState {
@@ -10,10 +71,11 @@ impl DCompState {
10
71
/// If the device is already initialized, it will return the existing state.
11
72
pub unsafe fn get_or_init (
12
73
& mut self ,
74
+ lib : & Arc < DCompLib > ,
13
75
hwnd : & HWND ,
14
76
) -> Result < & mut InnerState , crate :: SurfaceError > {
15
77
if self . inner . is_none ( ) {
16
- self . inner = Some ( unsafe { InnerState :: init ( hwnd) } ?) ;
78
+ self . inner = Some ( unsafe { InnerState :: init ( lib , hwnd) } ?) ;
17
79
}
18
80
Ok ( self . inner . as_mut ( ) . unwrap ( ) )
19
81
}
@@ -28,14 +90,9 @@ pub struct InnerState {
28
90
29
91
impl InnerState {
30
92
/// Creates a DirectComposition device and a target for the given window handle.
31
- pub unsafe fn init ( hwnd : & HWND ) -> Result < Self , crate :: SurfaceError > {
93
+ pub unsafe fn init ( lib : & Arc < DCompLib > , hwnd : & HWND ) -> Result < Self , crate :: SurfaceError > {
32
94
profiling:: scope!( "DCompState::init" ) ;
33
- let dcomp_device: DirectComposition :: IDCompositionDevice = {
34
- unsafe { DirectComposition :: DCompositionCreateDevice2 ( None ) } . map_err ( |err| {
35
- log:: error!( "DirectComposition::DCompositionCreateDevice failed: {err}" ) ;
36
- crate :: SurfaceError :: Other ( "DirectComposition::DCompositionCreateDevice" )
37
- } ) ?
38
- } ;
95
+ let dcomp_device = lib. create_device ( ) ?;
39
96
40
97
let target = unsafe { dcomp_device. CreateTargetForHwnd ( * hwnd, false ) } . map_err ( |err| {
41
98
log:: error!( "IDCompositionDevice::CreateTargetForHwnd failed: {err}" ) ;
0 commit comments