@@ -52,7 +52,7 @@ use windows::{
5252 core:: { Free , Interface } ,
5353 Win32 :: {
5454 Foundation ,
55- Graphics :: { Direct3D , Direct3D12 , DirectComposition , Dxgi } ,
55+ Graphics :: { Direct3D , Direct3D11 , Direct3D11on12 , Direct3D12 , DirectComposition , Dxgi } ,
5656 System :: Threading ,
5757 } ,
5858} ;
@@ -410,6 +410,7 @@ pub struct Instance {
410410 factory_media : Option < Dxgi :: IDXGIFactoryMedia > ,
411411 library : Arc < D3D12Lib > ,
412412 supports_allow_tearing : bool ,
413+ use_dcomp : bool ,
413414 _lib_dxgi : DxgiLib ,
414415 flags : wgt:: InstanceFlags ,
415416 dxc_container : Option < Arc < shader_compilation:: DxcContainer > > ,
@@ -479,9 +480,21 @@ struct SwapChain {
479480 size : wgt:: Extent3d ,
480481}
481482
483+ struct DCompState {
484+ visual : DirectComposition :: IDCompositionVisual ,
485+ device : DirectComposition :: IDCompositionDevice ,
486+ // Must be kept alive but is otherwise unused after initialization.
487+ _target : DirectComposition :: IDCompositionTarget ,
488+ }
489+
482490enum SurfaceTarget {
483491 /// Borrowed, lifetime externally managed
484492 WndHandle ( Foundation :: HWND ) ,
493+ /// `handle` is borrowed, lifetime externally managed
494+ VisualFromWndHandle {
495+ handle : Foundation :: HWND ,
496+ dcomp_state : RwLock < Option < DCompState > > ,
497+ } ,
485498 Visual ( DirectComposition :: IDCompositionVisual ) ,
486499 /// Borrowed, lifetime externally managed
487500 SurfaceHandle ( Foundation :: HANDLE ) ,
@@ -1147,6 +1160,61 @@ impl crate::Surface for Surface {
11471160 )
11481161 }
11491162 }
1163+ SurfaceTarget :: VisualFromWndHandle {
1164+ handle,
1165+ ref dcomp_state,
1166+ } => unsafe {
1167+ macro_rules! call {
1168+ ( $name: literal, $e: expr) => { {
1169+ profiling:: scope!( $name) ;
1170+ ( $e) . map_err( |_| crate :: SurfaceError :: Other ( $name) ) ?
1171+ } } ;
1172+ }
1173+
1174+ let mut d3d11_device = None ;
1175+ call ! (
1176+ "Direct3D11on12::D3D11On12CreateDevice" ,
1177+ Direct3D11on12 :: D3D11On12CreateDevice (
1178+ & device. raw,
1179+ Direct3D11 :: D3D11_CREATE_DEVICE_BGRA_SUPPORT . 0 ,
1180+ None ,
1181+ None ,
1182+ 0 ,
1183+ Some ( & mut d3d11_device) ,
1184+ None ,
1185+ None ,
1186+ )
1187+ ) ;
1188+ let d3d11_device = d3d11_device. unwrap ( ) ;
1189+ let dxgi_device: Dxgi :: IDXGIDevice =
1190+ call ! ( "IDXGIDevice::QueryInterface" , d3d11_device. cast( ) ) ;
1191+ let dcomp_device: DirectComposition :: IDCompositionDevice = call ! (
1192+ "DirectComposition::DCompositionCreateDevice" ,
1193+ DirectComposition :: DCompositionCreateDevice ( & dxgi_device)
1194+ ) ;
1195+ let target = call ! (
1196+ "IDCompositionDevice::CreateTargetForHwnd" ,
1197+ dcomp_device. CreateTargetForHwnd ( handle, false )
1198+ ) ;
1199+ let visual = call ! (
1200+ "IDCompositionDevice::CreateVisual" ,
1201+ dcomp_device. CreateVisual ( )
1202+ ) ;
1203+ call ! ( "IDCompositionTarget::SetRoot" , target. SetRoot ( & visual) ) ;
1204+
1205+ * dcomp_state. write ( ) = Some ( DCompState {
1206+ visual,
1207+ device : dcomp_device,
1208+ _target : target,
1209+ } ) ;
1210+
1211+ profiling:: scope!( "IDXGIFactory2::CreateSwapChainForComposition" ) ;
1212+ self . factory . CreateSwapChainForComposition (
1213+ & device. present_queue ,
1214+ & desc,
1215+ None ,
1216+ )
1217+ } ,
11501218 SurfaceTarget :: SurfaceHandle ( handle) => {
11511219 profiling:: scope!(
11521220 "IDXGIFactoryMedia::CreateSwapChainForCompositionSurfaceHandle"
@@ -1184,6 +1252,17 @@ impl crate::Surface for Surface {
11841252
11851253 match & self . target {
11861254 SurfaceTarget :: WndHandle ( _) | SurfaceTarget :: SurfaceHandle ( _) => { }
1255+ SurfaceTarget :: VisualFromWndHandle { dcomp_state, .. } => {
1256+ let dcomp_state = dcomp_state. read ( ) ;
1257+ let dcomp_state = dcomp_state
1258+ . as_ref ( )
1259+ . expect ( "dcomp_state was initialized above" ) ;
1260+ unsafe {
1261+ dcomp_state. visual . SetContent ( & swap_chain1) . map_err ( |_| {
1262+ crate :: SurfaceError :: Other ( "IDCompositionVisual::SetContent" )
1263+ } ) ?;
1264+ }
1265+ }
11871266 SurfaceTarget :: Visual ( visual) => {
11881267 if let Err ( err) = unsafe { visual. SetContent ( & swap_chain1) } {
11891268 log:: error!( "Unable to SetContent: {err}" ) ;
@@ -1221,6 +1300,7 @@ impl crate::Surface for Surface {
12211300 . into_device_result ( "MakeWindowAssociation" ) ?;
12221301 }
12231302 SurfaceTarget :: Visual ( _)
1303+ | SurfaceTarget :: VisualFromWndHandle { .. }
12241304 | SurfaceTarget :: SurfaceHandle ( _)
12251305 | SurfaceTarget :: SwapChainPanel ( _) => { }
12261306 }
@@ -1349,10 +1429,35 @@ impl crate::Queue for Queue {
13491429 m => unreachable ! ( "Cannot make surface with present mode {m:?}" ) ,
13501430 } ;
13511431
1352- profiling:: scope!( "IDXGISwapchain3::Present" ) ;
1353- unsafe { sc. raw . Present ( interval, flags) }
1354- . ok ( )
1355- . into_device_result ( "Present" ) ?;
1432+ unsafe {
1433+ profiling:: scope!( "IDXGISwapchain3::Present" ) ;
1434+ sc. raw . Present ( interval, flags)
1435+ }
1436+ . ok ( )
1437+ . into_device_result ( "Present" ) ?;
1438+
1439+ if let SurfaceTarget :: VisualFromWndHandle { dcomp_state, .. } = & surface. target {
1440+ let dcomp_state = dcomp_state. read ( ) ;
1441+ let dcomp_state = dcomp_state. as_ref ( ) . unwrap ( ) ;
1442+ unsafe {
1443+ if dcomp_state
1444+ . device
1445+ . CheckDeviceState ( )
1446+ . map_err ( |_| {
1447+ crate :: SurfaceError :: Other ( "IDCompositionDevice::CheckDeviceState" )
1448+ } ) ?
1449+ . into ( )
1450+ {
1451+ profiling:: scope!( "IDCompositionDevice::Commit" ) ;
1452+ dcomp_state
1453+ . device
1454+ . Commit ( )
1455+ . map_err ( |_| crate :: SurfaceError :: Other ( "IDCompositionDevice::Commit" ) ) ?;
1456+ } else {
1457+ return Err ( crate :: SurfaceError :: Lost ) ;
1458+ }
1459+ }
1460+ }
13561461
13571462 Ok ( ( ) )
13581463 }
0 commit comments