summaryrefslogtreecommitdiffstats
path: root/gfx/wr/direct-composition/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/wr/direct-composition/src/lib.rs')
-rw-r--r--gfx/wr/direct-composition/src/lib.rs179
1 files changed, 179 insertions, 0 deletions
diff --git a/gfx/wr/direct-composition/src/lib.rs b/gfx/wr/direct-composition/src/lib.rs
new file mode 100644
index 0000000000..fadb8f2b72
--- /dev/null
+++ b/gfx/wr/direct-composition/src/lib.rs
@@ -0,0 +1,179 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#![cfg(windows)]
+
+extern crate gleam;
+extern crate mozangle;
+extern crate winapi;
+
+use com::{ComPtr, CheckHResult, as_ptr};
+use std::ptr;
+use std::rc::Rc;
+use winapi::shared::dxgi1_2::DXGI_SWAP_CHAIN_DESC1;
+use winapi::shared::dxgi1_2::IDXGIFactory2;
+use winapi::shared::minwindef::{TRUE, FALSE};
+use winapi::shared::windef::HWND;
+use winapi::um::d3d11::ID3D11Device;
+use winapi::um::dcomp::IDCompositionDevice;
+use winapi::um::dcomp::IDCompositionTarget;
+use winapi::um::dcomp::IDCompositionVisual;
+
+mod com;
+mod egl;
+
+pub struct DirectComposition {
+ d3d_device: ComPtr<ID3D11Device>,
+ dxgi_factory: ComPtr<IDXGIFactory2>,
+
+ egl: Rc<egl::SharedEglThings>,
+ pub gleam: Rc<dyn gleam::gl::Gl>,
+
+ composition_device: ComPtr<IDCompositionDevice>,
+ root_visual: ComPtr<IDCompositionVisual>,
+
+ #[allow(unused)] // Needs to be kept alive
+ composition_target: ComPtr<IDCompositionTarget>,
+}
+
+impl DirectComposition {
+ /// Initialize DirectComposition in the given window
+ ///
+ /// # Safety
+ ///
+ /// `hwnd` must be a valid handle to a window.
+ pub unsafe fn new(hwnd: HWND) -> Self {
+ let d3d_device = ComPtr::new_with(|ptr_ptr| winapi::um::d3d11::D3D11CreateDevice(
+ ptr::null_mut(),
+ winapi::um::d3dcommon::D3D_DRIVER_TYPE_HARDWARE,
+ ptr::null_mut(),
+ winapi::um::d3d11::D3D11_CREATE_DEVICE_BGRA_SUPPORT |
+ if cfg!(debug_assertions) {
+ winapi::um::d3d11::D3D11_CREATE_DEVICE_DEBUG
+ } else {
+ 0
+ },
+ ptr::null_mut(),
+ 0,
+ winapi::um::d3d11::D3D11_SDK_VERSION,
+ ptr_ptr,
+ &mut 0,
+ ptr::null_mut(),
+ ));
+
+ let egl = egl::SharedEglThings::new(d3d_device.as_raw());
+ let gleam = gleam::gl::GlesFns::load_with(egl::get_proc_address);
+
+ let dxgi_device = d3d_device.cast::<winapi::shared::dxgi::IDXGIDevice>();
+
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404556(v=vs.85).aspx#code-snippet-1
+ // “Because you can create a Direct3D device without creating a swap chain,
+ // you might need to retrieve the factory that is used to create the device
+ // in order to create a swap chain.”
+ let adapter = ComPtr::new_with(|ptr_ptr| dxgi_device.GetAdapter(ptr_ptr));
+ let dxgi_factory = ComPtr::<IDXGIFactory2>::new_with_uuid(|uuid, ptr_ptr| {
+ adapter.GetParent(uuid, ptr_ptr)
+ });
+
+ // Create the DirectComposition device object.
+ let composition_device = ComPtr::<IDCompositionDevice>::new_with_uuid(|uuid, ptr_ptr| {
+ winapi::um::dcomp::DCompositionCreateDevice(&*dxgi_device, uuid, ptr_ptr)
+ });
+
+ // Create the composition target object based on the
+ // specified application window.
+ let composition_target = ComPtr::new_with(|ptr_ptr| {
+ composition_device.CreateTargetForHwnd(hwnd, TRUE, ptr_ptr)
+ });
+
+ let root_visual = ComPtr::new_with(|ptr_ptr| composition_device.CreateVisual(ptr_ptr));
+ composition_target.SetRoot(&*root_visual).check_hresult();
+
+ DirectComposition {
+ d3d_device, dxgi_factory,
+ egl, gleam,
+ composition_device, composition_target, root_visual,
+ }
+ }
+
+ /// Execute changes to the DirectComposition scene.
+ pub fn commit(&self) {
+ unsafe {
+ self.composition_device.Commit().check_hresult()
+ }
+ }
+
+ pub fn create_angle_visual(&self, width: u32, height: u32) -> AngleVisual {
+ unsafe {
+ let desc = DXGI_SWAP_CHAIN_DESC1 {
+ Width: width,
+ Height: height,
+ Format: winapi::shared::dxgiformat::DXGI_FORMAT_B8G8R8A8_UNORM,
+ Stereo: FALSE,
+ SampleDesc: winapi::shared::dxgitype::DXGI_SAMPLE_DESC {
+ Count: 1,
+ Quality: 0,
+ },
+ BufferUsage: winapi::shared::dxgitype::DXGI_USAGE_RENDER_TARGET_OUTPUT,
+ BufferCount: 2,
+ Scaling: winapi::shared::dxgi1_2::DXGI_SCALING_STRETCH,
+ SwapEffect: winapi::shared::dxgi::DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL,
+ AlphaMode: winapi::shared::dxgi1_2::DXGI_ALPHA_MODE_PREMULTIPLIED,
+ Flags: 0,
+ };
+ let swap_chain = ComPtr::<winapi::shared::dxgi1_2::IDXGISwapChain1>::new_with(|ptr_ptr| {
+ self.dxgi_factory.CreateSwapChainForComposition(
+ as_ptr(&self.d3d_device),
+ &desc,
+ ptr::null_mut(),
+ ptr_ptr,
+ )
+ });
+ let back_buffer = ComPtr::<winapi::um::d3d11::ID3D11Texture2D>::new_with_uuid(|uuid, ptr_ptr| {
+ swap_chain.GetBuffer(0, uuid, ptr_ptr)
+ });
+ let egl = egl::PerVisualEglThings::new(self.egl.clone(), &*back_buffer, width, height);
+ let gleam = self.gleam.clone();
+
+ let visual = ComPtr::new_with(|ptr_ptr| self.composition_device.CreateVisual(ptr_ptr));
+ visual.SetContent(&*****swap_chain).check_hresult();
+ self.root_visual.AddVisual(&*visual, FALSE, ptr::null_mut()).check_hresult();
+
+ AngleVisual { visual, swap_chain, egl, gleam }
+ }
+ }
+}
+
+/// A DirectComposition "visual" configured for rendering with Direct3D.
+pub struct AngleVisual {
+ visual: ComPtr<IDCompositionVisual>,
+ swap_chain: ComPtr<winapi::shared::dxgi1_2::IDXGISwapChain1>,
+ egl: egl::PerVisualEglThings,
+ pub gleam: Rc<dyn gleam::gl::Gl>,
+}
+
+impl AngleVisual {
+ pub fn set_offset_x(&self, offset_x: f32) {
+ unsafe {
+ self.visual.SetOffsetX_1(offset_x).check_hresult()
+ }
+ }
+
+ pub fn set_offset_y(&self, offset_y: f32) {
+ unsafe {
+ self.visual.SetOffsetY_1(offset_y).check_hresult()
+ }
+ }
+
+ pub fn make_current(&self) {
+ self.egl.make_current()
+ }
+
+ pub fn present(&self) {
+ self.gleam.finish();
+ unsafe {
+ self.swap_chain.Present(0, 0).check_hresult()
+ }
+ }
+}