From 290f6e4ffa52e153cf27a25d281a0ff9c00b06d2 Mon Sep 17 00:00:00 2001 From: Raph Levien Date: Thu, 20 Aug 2020 13:55:51 -0700 Subject: [PATCH] Clean up Mostly deleting unused code, removing alternate code paths, as everything is now a straightforward DXGI strategy. --- druid-shell/src/platform/windows/dcomp.rs | 197 ------------ druid-shell/src/platform/windows/mod.rs | 89 +----- druid-shell/src/platform/windows/paint.rs | 34 +-- druid-shell/src/platform/windows/util.rs | 35 --- druid-shell/src/platform/windows/window.rs | 337 ++++++--------------- 5 files changed, 101 insertions(+), 591 deletions(-) diff --git a/druid-shell/src/platform/windows/dcomp.rs b/druid-shell/src/platform/windows/dcomp.rs index 47d6175f07..908d063824 100644 --- a/druid-shell/src/platform/windows/dcomp.rs +++ b/druid-shell/src/platform/windows/dcomp.rs @@ -16,33 +16,18 @@ // This module could become a general wrapper for DirectComposition, but // for now we're just using what we need to get a swapchain up. -#![allow(unused)] -use std::mem; -use std::ops::{Deref, DerefMut}; use std::ptr::{null, null_mut}; use log::error; -use winapi::shared::dxgi::IDXGIDevice; -use winapi::shared::dxgi1_2::DXGI_ALPHA_MODE_IGNORE; -use winapi::shared::dxgiformat::DXGI_FORMAT_B8G8R8A8_UNORM; -use winapi::shared::minwindef::{FALSE, TRUE}; -use winapi::shared::windef::{HWND, POINT, RECT}; use winapi::shared::winerror::SUCCEEDED; -use winapi::um::d2d1::*; -use winapi::um::d2d1_1::*; use winapi::um::d3d11::*; use winapi::um::d3dcommon::D3D_DRIVER_TYPE_HARDWARE; -use winapi::um::dcomp::*; -use winapi::um::dcompanimation::*; -use winapi::um::unknwnbase::IUnknown; use winapi::um::winnt::HRESULT; use winapi::Interface; use wio::com::ComPtr; -use super::util::OPTIONAL_FUNCTIONS; - unsafe fn wrap(hr: HRESULT, ptr: *mut T, f: F) -> Result where F: Fn(ComPtr) -> U, @@ -55,25 +40,7 @@ where } } -fn unit_err(hr: HRESULT) -> Result<(), HRESULT> { - if SUCCEEDED(hr) { - Ok(()) - } else { - Err(hr) - } -} - pub struct D3D11Device(ComPtr); -pub struct D2D1Device(ComPtr); -pub struct DCompositionDevice(ComPtr); -pub struct DCompositionTarget(ComPtr); -pub struct DCompositionVisual(ComPtr); -pub struct DCompositionVirtualSurface(ComPtr); - -/// A trait for content which can be added to a visual. -pub(crate) trait Content { - unsafe fn unknown_ptr(&mut self) -> *mut IUnknown; -} impl D3D11Device { /// Creates a new device with basic defaults. @@ -100,171 +67,7 @@ impl D3D11Device { } } - pub(crate) fn create_d2d1_device(&mut self) -> Result { - unsafe { - let mut dxgi_device: ComPtr = self.0.cast()?; - let mut d2d1_device: *mut ID2D1Device = null_mut(); - let hr = D2D1CreateDevice(dxgi_device.as_raw(), null(), &mut d2d1_device); - wrap(hr, d2d1_device, D2D1Device) - } - } - pub(crate) fn raw_ptr(&mut self) -> *mut ID3D11Device { self.0.as_raw() } } - -impl D2D1Device { - /// Create a wrapped DCompositionDevice object. Note: returns Err(0) on systems - /// not supporting DirectComposition, available 8.1 and above. - pub(crate) fn create_composition_device(&mut self) -> Result { - unsafe { - let create = OPTIONAL_FUNCTIONS.DCompositionCreateDevice2.ok_or(0)?; - let mut dcomp_device: *mut IDCompositionDevice = null_mut(); - let hr = create( - self.0.as_raw() as *mut IUnknown, - &IDCompositionDevice::uuidof(), - &mut dcomp_device as *mut _ as *mut _, - ); - wrap(hr, dcomp_device, DCompositionDevice) - } - } -} - -impl DCompositionDevice { - pub(crate) unsafe fn create_target_for_hwnd( - &mut self, - hwnd: HWND, - topmost: bool, - ) -> Result { - let mut dcomp_target: *mut IDCompositionTarget = null_mut(); - let hr = - self.0 - .CreateTargetForHwnd(hwnd, if topmost { TRUE } else { FALSE }, &mut dcomp_target); - wrap(hr, dcomp_target, DCompositionTarget) - } - - pub(crate) fn create_visual(&mut self) -> Result { - unsafe { - let mut visual: *mut IDCompositionVisual = null_mut(); - let hr = self.0.CreateVisual(&mut visual); - wrap(hr, visual, DCompositionVisual) - } - } - - /// Creates an RGB surface. Probably should allow more options (including alpha). - pub(crate) fn create_virtual_surface( - &mut self, - height: u32, - width: u32, - ) -> Result { - unsafe { - let mut surface: *mut IDCompositionVirtualSurface = null_mut(); - let hr = self.0.CreateVirtualSurface( - width, - height, - DXGI_FORMAT_B8G8R8A8_UNORM, - DXGI_ALPHA_MODE_IGNORE, - &mut surface, - ); - wrap(hr, surface, DCompositionVirtualSurface) - } - } - - pub(crate) fn commit(&mut self) -> Result<(), HRESULT> { - unsafe { unit_err(self.0.Commit()) } - } -} - -impl DCompositionTarget { - // alternatively could be set_root with an option - pub(crate) fn clear_root(&mut self) -> Result<(), HRESULT> { - unsafe { unit_err(self.0.SetRoot(null_mut())) } - } - - pub(crate) fn set_root(&mut self, visual: &mut DCompositionVisual) -> Result<(), HRESULT> { - unsafe { unit_err(self.0.SetRoot(visual.0.as_raw())) } - } -} - -impl DCompositionVisual { - pub(crate) fn set_content(&mut self, content: &mut T) -> Result<(), HRESULT> { - unsafe { self.set_content_raw(content.unknown_ptr()) } - } - - // TODO: impl Content trait for swapchain, for type safety - pub(crate) unsafe fn set_content_raw(&mut self, content: *mut IUnknown) -> Result<(), HRESULT> { - unit_err(self.0.SetContent(content)) - } - - pub(crate) fn set_pos(&mut self, x: f32, y: f32) { - unsafe { - self.0.SetOffsetX_1(x); - self.0.SetOffsetY_1(y); - } - } -} - -// We don't actually need to draw into DirectComposition virtual surfaces now, this is -// experimental and based on an older version of direct2d-rs. Probably delete. - -/* -struct DcBacking(*mut ID2D1DeviceContext); -unsafe impl RenderTargetBacking for DcBacking { - fn create_target(self, _factory: &mut ID2D1Factory1) -> Result<*mut ID2D1RenderTarget, HRESULT> { - Ok(self.0 as *mut ID2D1RenderTarget) - } -} - -// TODO: support common methods with DCompositionSurface, probably should be trait -impl DCompositionVirtualSurface { - // could try to expose more DeviceContext capability - pub fn begin_draw(&mut self, d2d_factory: &direct2d::Factory, rect: Option) - -> Result - { - unsafe { - let mut dc: *mut ID2D1DeviceContext = null_mut(); - let rect_ptr = match rect { - None => null(), - Some(r) => &r, - }; - let mut offset: POINT = mem::uninitialized(); - let hr = self.0.BeginDraw(rect_ptr, &ID2D1DeviceContext::uuidof(), - &mut dc as *mut _ as *mut _, &mut offset); - if !SUCCEEDED(hr) { - return Err(hr); - } - let backing = DcBacking(dc); - let mut rt = d2d_factory.create_render_target(backing).map_err(|e| - match e { - direct2d::Error::ComError(hr) => hr, - _ => 0, - })?; - // TODO: either move dpi scaling somewhere else or figure out how to - // set it correctly here. - rt.set_transform(&Matrix3x2F::new([[2.0, 0.0], [0.0, 2.0], - [offset.x as f32, offset.y as f32]])); - Ok(rt) - } - } - - pub fn end_draw(&mut self) -> Result<(), HRESULT> { - unsafe { - unit_err(self.0.EndDraw()) - } - } - - pub fn resize(&mut self, width: u32, height: u32) -> Result<(), HRESULT> { - unsafe { - unit_err(self.0.Resize(width, height)) - } - } -} - -impl Content for DCompositionVirtualSurface { - unsafe fn unknown_ptr(&mut self) -> *mut IUnknown { - self.0.as_raw() as *mut IUnknown - } -} - -*/ diff --git a/druid-shell/src/platform/windows/mod.rs b/druid-shell/src/platform/windows/mod.rs index e5b330ba01..4834da09db 100644 --- a/druid-shell/src/platform/windows/mod.rs +++ b/druid-shell/src/platform/windows/mod.rs @@ -45,95 +45,12 @@ pub mod window; // Basically, go from HwndRenderTarget or DxgiSurfaceRenderTarget (2d or 3d) to a Device Context. // Go back up for particular needs. -use piet_common::d2d::{D2DFactory, DeviceContext}; +use piet_common::d2d::DeviceContext; use std::fmt::{Debug, Display, Formatter}; -use winapi::shared::windef::HWND; -use winapi::shared::winerror::{HRESULT, SUCCEEDED}; -use winapi::um::d2d1::{ - ID2D1HwndRenderTarget, ID2D1RenderTarget, D2D1_HWND_RENDER_TARGET_PROPERTIES, - D2D1_RENDER_TARGET_PROPERTIES, D2D1_SIZE_U, -}; -use winapi::um::dcommon::D2D1_PIXEL_FORMAT; +use winapi::shared::winerror::HRESULT; +use winapi::um::d2d1::ID2D1RenderTarget; use wio::com::ComPtr; -#[derive(Clone)] -pub struct HwndRenderTarget { - ptr: ComPtr, -} - -impl HwndRenderTarget { - pub fn create( - factory: &D2DFactory, - hwnd: HWND, - width: u32, - height: u32, - ) -> Result { - // hardcode - // - RenderTargetType::Default - // - AlphaMode::Unknown - let rt_props = DEFAULT_PROPS; - let mut hwnd_props = DEFAULT_HWND_PROPS; - - hwnd_props.hwnd = hwnd; - hwnd_props.pixelSize.width = width; - hwnd_props.pixelSize.height = height; - - // now build - unsafe { - let mut ptr = std::ptr::null_mut(); - let hr = (*factory.get_raw()).CreateHwndRenderTarget(&rt_props, &hwnd_props, &mut ptr); - - if SUCCEEDED(hr) { - Ok(HwndRenderTarget::from_raw(ptr)) - } else { - Err(hr.into()) - } - } - } - - /// construct from COM ptr - /// - /// # Safety - /// TODO - pub unsafe fn from_ptr(ptr: ComPtr) -> Self { - Self { ptr } - } - - /// construct from raw ptr - /// - /// # Safety - /// TODO - pub unsafe fn from_raw(raw: *mut ID2D1HwndRenderTarget) -> Self { - Self::from_ptr(ComPtr::from_raw(raw)) - } - - pub fn get_comptr(&self) -> &ComPtr { - &self.ptr - } -} - -// props for creating hwnd render target -const DEFAULT_PROPS: D2D1_RENDER_TARGET_PROPERTIES = D2D1_RENDER_TARGET_PROPERTIES { - _type: 0u32, //RenderTargetType::Default - pixelFormat: D2D1_PIXEL_FORMAT { - format: 87u32, //Format::B8G8R8A8Unorm, see https://docs.rs/dxgi/0.3.0-alpha4/src/dxgi/enums/format.rs.html#631 - alphaMode: 0u32, //AlphaMode::Unknown - }, - dpiX: 0.0, - dpiY: 0.0, - usage: 0, - minLevel: 0, -}; - -const DEFAULT_HWND_PROPS: D2D1_HWND_RENDER_TARGET_PROPERTIES = D2D1_HWND_RENDER_TARGET_PROPERTIES { - hwnd: std::ptr::null_mut(), - pixelSize: D2D1_SIZE_U { - width: 0, - height: 0, - }, - presentOptions: 0, -}; - #[derive(Clone)] pub struct DxgiSurfaceRenderTarget { ptr: ComPtr, diff --git a/druid-shell/src/platform/windows/paint.rs b/druid-shell/src/platform/windows/paint.rs index 6fc165c7c1..2253d13ac5 100644 --- a/druid-shell/src/platform/windows/paint.rs +++ b/druid-shell/src/platform/windows/paint.rs @@ -19,50 +19,26 @@ //! dxgi render targets so we can use present options for minimal //! invalidation and low-latency frame timing. -use std::mem; use std::ptr::null_mut; use winapi::ctypes::c_void; use winapi::shared::dxgi::*; use winapi::shared::dxgi1_2::*; use winapi::shared::dxgiformat::*; -use winapi::shared::windef::*; use winapi::shared::winerror::*; use winapi::um::d2d1::*; use winapi::um::dcommon::*; -use winapi::um::winuser::*; use winapi::Interface; use piet_common::d2d::D2DFactory; -use crate::platform::windows::{DeviceContext, DxgiSurfaceRenderTarget, HwndRenderTarget}; +use crate::platform::windows::DxgiSurfaceRenderTarget; use crate::scale::Scale; use super::error::Error; use super::util::as_result; use super::window::SCALE_TARGET_DPI; -pub(crate) unsafe fn create_render_target( - d2d_factory: &D2DFactory, - hwnd: HWND, -) -> Result { - let mut rect: RECT = mem::zeroed(); - if GetClientRect(hwnd, &mut rect) == 0 { - log::warn!("GetClientRect failed."); - Err(Error::D2Error) - } else { - let width = (rect.right - rect.left) as u32; - let height = (rect.bottom - rect.top) as u32; - let res = HwndRenderTarget::create(d2d_factory, hwnd, width, height); - - if let Err(ref e) = res { - log::error!("Creating hwnd render target failed: {:?}", e); - } - res.map(|hrt| cast_to_device_context(&hrt).expect("removethis")) - .map_err(|_| Error::D2Error) - } -} - /// Create a render target from a DXGI swapchain. /// /// TODO: probably want to create a DeviceContext, it's more flexible. @@ -100,11 +76,3 @@ pub(crate) unsafe fn create_render_target_dxgi( Err(res.into()) } } - -/// Casts hwnd variant to DeviceTarget -unsafe fn cast_to_device_context(hrt: &HwndRenderTarget) -> Option { - hrt.get_comptr() - .cast() - .ok() - .map(|com_ptr| DeviceContext::new(com_ptr)) -} diff --git a/druid-shell/src/platform/windows/util.rs b/druid-shell/src/platform/windows/util.rs index e91d12d42b..ee96d24e22 100644 --- a/druid-shell/src/platform/windows/util.rs +++ b/druid-shell/src/platform/windows/util.rs @@ -24,8 +24,6 @@ use std::ptr; use std::slice; use lazy_static::lazy_static; -use winapi::ctypes::c_void; -use winapi::shared::guiddef::REFIID; use winapi::shared::minwindef::{HMODULE, UINT}; use winapi::shared::ntdef::{HRESULT, LPWSTR}; use winapi::shared::windef::{HMONITOR, RECT}; @@ -35,7 +33,6 @@ use winapi::um::handleapi::INVALID_HANDLE_VALUE; use winapi::um::libloaderapi::{GetModuleHandleW, GetProcAddress, LoadLibraryW}; use winapi::um::processenv::{GetStdHandle, SetStdHandle}; use winapi::um::shellscalingapi::{MONITOR_DPI_TYPE, PROCESS_DPI_AWARENESS}; -use winapi::um::unknwnbase::IUnknown; use winapi::um::winbase::{FILE_TYPE_UNKNOWN, STD_ERROR_HANDLE, STD_OUTPUT_HANDLE}; use winapi::um::wincon::{AttachConsole, ATTACH_PARENT_PROCESS}; use winapi::um::winnt::{FILE_SHARE_WRITE, GENERIC_READ, GENERIC_WRITE}; @@ -133,24 +130,12 @@ type GetDpiForSystem = unsafe extern "system" fn() -> UINT; type GetDpiForMonitor = unsafe extern "system" fn(HMONITOR, MONITOR_DPI_TYPE, *mut UINT, *mut UINT); // from user32.dll type SetProcessDpiAwareness = unsafe extern "system" fn(PROCESS_DPI_AWARENESS) -> HRESULT; -type DCompositionCreateDevice2 = unsafe extern "system" fn( - renderingDevice: *const IUnknown, - iid: REFIID, - dcompositionDevice: *mut *mut c_void, -) -> HRESULT; -type CreateDXGIFactory1 = - unsafe extern "system" fn(riid: REFIID, ppFactory: *mut *mut c_void) -> HRESULT; -type CreateDXGIFactory2 = - unsafe extern "system" fn(Flags: UINT, riid: REFIID, ppFactory: *mut *mut c_void) -> HRESULT; #[allow(non_snake_case)] // For member fields pub struct OptionalFunctions { pub GetDpiForSystem: Option, pub GetDpiForMonitor: Option, pub SetProcessDpiAwareness: Option, - pub DCompositionCreateDevice2: Option, - pub CreateDXGIFactory1: Option, - pub CreateDXGIFactory2: Option, } #[allow(non_snake_case)] // For local variables @@ -196,15 +181,10 @@ fn load_optional_functions() -> OptionalFunctions { let shcore = load_library("shcore.dll"); let user32 = load_library("user32.dll"); - let dcomp = load_library("dcomp.dll"); - let dxgi = load_library("dxgi.dll"); let mut GetDpiForSystem = None; let mut GetDpiForMonitor = None; let mut SetProcessDpiAwareness = None; - let mut DCompositionCreateDevice2 = None; - let mut CreateDXGIFactory1 = None; - let mut CreateDXGIFactory2 = None; if shcore.is_null() { log::info!("No shcore.dll"); @@ -219,25 +199,10 @@ fn load_optional_functions() -> OptionalFunctions { load_function!(user32, GetDpiForSystem, "10"); } - if !dcomp.is_null() { - load_function!(dcomp, DCompositionCreateDevice2, "8.1"); - } - - if !dxgi.is_null() { - load_function!(dxgi, CreateDXGIFactory1, "7.0"); - } - - if !dxgi.is_null() { - load_function!(dxgi, CreateDXGIFactory2, "8.1"); - } - OptionalFunctions { GetDpiForSystem, GetDpiForMonitor, SetProcessDpiAwareness, - DCompositionCreateDevice2, - CreateDXGIFactory1, - CreateDXGIFactory2, } } diff --git a/druid-shell/src/platform/windows/window.rs b/druid-shell/src/platform/windows/window.rs index f31e9f38a3..9d064e5a00 100644 --- a/druid-shell/src/platform/windows/window.rs +++ b/druid-shell/src/platform/windows/window.rs @@ -32,7 +32,6 @@ use winapi::shared::dxgitype::*; use winapi::shared::minwindef::*; use winapi::shared::windef::*; use winapi::shared::winerror::*; -use winapi::um::d2d1::*; use winapi::um::errhandlingapi::GetLastError; use winapi::um::unknwnbase::*; use winapi::um::winnt::*; @@ -41,14 +40,12 @@ use winapi::um::winuser::*; use piet_common::d2d::{D2DFactory, DeviceContext}; use piet_common::dwrite::DwriteFactory; -use crate::platform::windows::HwndRenderTarget; - use crate::kurbo::{Point, Rect, Size, Vec2}; use crate::piet::{Piet, RenderContext}; use super::accels::register_accel; use super::application::Application; -use super::dcomp::{D3D11Device, DCompositionDevice, DCompositionTarget, DCompositionVisual}; +use super::dcomp::D3D11Device; use super::dialog::get_file_dialog_path; use super::error::Error; use super::keyboard::KeyboardState; @@ -70,10 +67,6 @@ use crate::window::{IdleToken, Text, TimerToken, WinHandler}; /// Windows considers 96 the default value which represents a 1.0 scale factor. pub(crate) const SCALE_TARGET_DPI: f64 = 96.0; -extern "system" { - pub fn DwmFlush(); -} - /// Builder abstraction for creating new windows. pub(crate) struct WindowBuilder { app: Application, @@ -92,21 +85,22 @@ pub(crate) struct WindowBuilder { /// good performance on Windows. This setting lets clients experiment /// with different strategies. pub enum PresentStrategy { - /// Don't try to use DXGI at all, only create Hwnd render targets. - /// Note: on Windows 7 this is the only mode available. - Hwnd, - - /// Corresponds to the swap effect DXGI_SWAP_EFFECT_SEQUENTIAL. In - /// testing, it causes diagonal banding artifacts with Nvidia - /// adapters, and incremental present doesn't work. However, it - /// is compatible with GDI (such as menus). - #[allow(dead_code)] + /// Corresponds to the swap effect DXGI_SWAP_EFFECT_SEQUENTIAL. It + /// is compatible with GDI (such as menus), but is not the best in + /// performance. + /// + /// In earlier testing, it exhibited diagonal banding artifacts (most + /// likely because of bugs in Nvidia Optimus configurations) and did + /// not do incremental present, but in more recent testing, at least + /// incremental present seems to work fine. + /// + /// Also note, this swap effect is not compatible with DX12. Sequential, /// Corresponds to the swap effect DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL. - /// In testing, it seems to perform well (including allowing smooth - /// resizing when the frame can be rendered quickly), but isn't - /// compatible with GDI. + /// In testing, it seems to perform well, but isn't compatible with + /// GDI. Resize can probably be made to work reasonably smoothly with + /// additional synchronization work, but has some artifacts. Flip, /// Corresponds to the swap effect DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL @@ -174,7 +168,7 @@ struct MyWndProc { struct WndState { handler: Box, render_target: Option, - dcomp_state: Option, + dxgi_state: Option, min_size: Option, keyboard_state: KeyboardState, // Stores a set of all mouse buttons that are currently holding mouse @@ -186,12 +180,9 @@ struct WndState { //TODO: track surrogate orphan } -/// State for DirectComposition. This is optional because it is only supported -/// on 8.1 and up. -struct DCompState { +/// State for DXGI swapchains. +struct DxgiState { swap_chain: *mut IDXGISwapChain1, - // True if in a drag-resizing gesture (at which point the swapchain is disabled) - sizing: bool, } /// Message indicating there are idle tasks to run. @@ -211,8 +202,6 @@ pub(crate) const DS_REQUEST_DESTROY: UINT = WM_USER + 1; impl Default for PresentStrategy { fn default() -> PresentStrategy { - // We probably want to change this, but we need GDI to work. Too bad about - // the artifacty resizing. PresentStrategy::Sequential } } @@ -257,7 +246,7 @@ fn is_point_in_client_rect(hwnd: HWND, x: i32, y: i32) -> bool { impl WndState { fn rebuild_render_target(&mut self, d2d: &D2DFactory, scale: Scale) { unsafe { - let swap_chain = self.dcomp_state.as_ref().unwrap().swap_chain; + let swap_chain = self.dxgi_state.as_ref().unwrap().swap_chain; let rt = paint::create_render_target_dxgi(d2d, swap_chain, scale) .map(|rt| rt.as_device_context().expect("TODO remove this expect")); self.render_target = rt.ok(); @@ -343,10 +332,6 @@ impl MyWndProc { self.with_window_state(|state| state.scale.get()) } - fn area(&self) -> ScaledArea { - self.with_window_state(|state| state.area.get()) - } - fn set_area(&self, area: ScaledArea) { self.with_window_state(move |state| state.area.set(area)) } @@ -387,19 +372,13 @@ impl WndProc for MyWndProc { state.hwnd.set(hwnd); } if let Some(state) = self.state.borrow_mut().as_mut() { - let dcomp_state = unsafe { - create_dcomp_state(self.present_strategy, hwnd).unwrap_or_else(|e| { - warn!("Creating swapchain failed, falling back to hwnd: {:?}", e); + let dxgi_state = unsafe { + create_dxgi_state(self.present_strategy, hwnd).unwrap_or_else(|e| { + error!("Creating swapchain failed: {:?}", e); None }) }; - if dcomp_state.is_none() { - unsafe { - let rt = paint::create_render_target(&self.d2d_factory, hwnd); - state.render_target = rt.ok(); - } - } - state.dcomp_state = dcomp_state; + state.dxgi_state = dxgi_state; let handle = self.handle.borrow().to_owned(); state.handler.connect(&handle.into()); @@ -421,10 +400,6 @@ impl WndProc for MyWndProc { let mut rect: RECT = mem::zeroed(); GetUpdateRect(hwnd, &mut rect, FALSE); let s = s.as_mut().unwrap(); - if s.render_target.is_none() { - let rt = paint::create_render_target(&self.d2d_factory, hwnd); - s.render_target = rt.ok(); - } s.handler.rebuild_resources(); let rect_dp = util::recti_to_rect(rect).to_dp(self.scale()); s.render( @@ -433,17 +408,14 @@ impl WndProc for MyWndProc { &self.handle, rect_dp, ); - if let Some(ref mut ds) = s.dcomp_state { + if let Some(ref mut ds) = s.dxgi_state { let params = DXGI_PRESENT_PARAMETERS { DirtyRectsCount: 1, pDirtyRects: &mut rect, pScrollRect: null_mut(), pScrollOffset: null_mut(), }; - if !ds.sizing { - (*ds.swap_chain).Present1(1, 0, ¶ms); - //let _ = ds.dcomp_device.commit(); - } + (*ds.swap_chain).Present1(1, 0, ¶ms); } ValidateRect(hwnd, null_mut()); } else { @@ -451,82 +423,6 @@ impl WndProc for MyWndProc { } Some(0) }, - /* - WM_ENTERSIZEMOVE => unsafe { - if let Ok(mut s) = self.state.try_borrow_mut() { - let s = s.as_mut().unwrap(); - if s.dcomp_state.is_some() { - let rt = paint::create_render_target(&self.d2d_factory, hwnd); - s.render_target = rt.ok(); - { - let rect_dp = self.area().size_dp().to_rect(); - s.handler.rebuild_resources(); - s.render( - &self.d2d_factory, - &self.dwrite_factory, - &self.handle, - rect_dp, - ); - } - - /* - if let Some(ref mut ds) = s.dcomp_state { - let _ = ds.dcomp_target.clear_root(); - let _ = ds.dcomp_device.commit(); - ds.sizing = true; - } - */ - } - } else { - self.log_dropped_msg(hwnd, msg, wparam, lparam); - } - None - }, - WM_EXITSIZEMOVE => unsafe { - if let Ok(mut s) = self.state.try_borrow_mut() { - let s = s.as_mut().unwrap(); - if s.dcomp_state.is_some() { - let area = self.area(); - let size_px = area.size_px(); - let res = (*s.dcomp_state.as_mut().unwrap().swap_chain).ResizeBuffers( - 2, - size_px.width as u32, - size_px.height as u32, - DXGI_FORMAT_UNKNOWN, - 0, - ); - if SUCCEEDED(res) { - s.handler.rebuild_resources(); - s.rebuild_render_target(&self.d2d_factory, self.scale()); - s.render( - &self.d2d_factory, - &self.dwrite_factory, - &self.handle, - area.size_dp().to_rect(), - ); - (*s.dcomp_state.as_ref().unwrap().swap_chain).Present(0, 0); - } else { - error!("ResizeBuffers failed: 0x{:x}", res); - } - - // Flush to present flicker artifact (old swapchain composited) - // It might actually be better to create a new swapchain here. - DwmFlush(); - - /* - if let Some(ref mut ds) = s.dcomp_state { - let _ = ds.dcomp_target.set_root(&mut ds.swapchain_visual); - let _ = ds.dcomp_device.commit(); - ds.sizing = false; - } - */ - } - } else { - self.log_dropped_msg(hwnd, msg, wparam, lparam); - } - None - }, - */ WM_SIZE => unsafe { if let Ok(mut s) = self.state.try_borrow_mut() { let s = s.as_mut().unwrap(); @@ -537,52 +433,31 @@ impl WndProc for MyWndProc { let size_dp = area.size_dp(); self.set_area(area); s.handler.size(size_dp); - let use_hwnd = if let Some(ref dcomp_state) = s.dcomp_state { - dcomp_state.sizing - } else { - true - }; - if use_hwnd { - if let Some(ref mut rt) = s.render_target { - if let Some(hrt) = cast_to_hwnd(rt) { - let size = D2D1_SIZE_U { width, height }; - let _ = hrt.ptr.Resize(&size); - } - } - if InvalidateRect(hwnd, null(), FALSE) == FALSE { - log::warn!( - "InvalidateRect failed: {}", - Error::Hr(HRESULT_FROM_WIN32(GetLastError())) - ); + let res; + { + s.render_target = None; + res = (*s.dxgi_state.as_mut().unwrap().swap_chain).ResizeBuffers( + 0, + width, + height, + DXGI_FORMAT_UNKNOWN, + 0, + ); + } + if SUCCEEDED(res) { + s.rebuild_render_target(&self.d2d_factory, scale); + s.render( + &self.d2d_factory, + &self.dwrite_factory, + &self.handle, + size_dp.to_rect(), + ); + if let Some(ref mut dxgi_state) = s.dxgi_state { + (*dxgi_state.swap_chain).Present(0, 0); } + ValidateRect(hwnd, null_mut()); } else { - let res; - { - s.render_target = None; - res = (*s.dcomp_state.as_mut().unwrap().swap_chain).ResizeBuffers( - 0, - width, - height, - DXGI_FORMAT_UNKNOWN, - 0, - ); - } - if SUCCEEDED(res) { - s.rebuild_render_target(&self.d2d_factory, scale); - s.render( - &self.d2d_factory, - &self.dwrite_factory, - &self.handle, - size_dp.to_rect(), - ); - if let Some(ref mut dcomp_state) = s.dcomp_state { - (*dcomp_state.swap_chain).Present(0, 0); - //let _ = dcomp_state.dcomp_device.commit(); - } - ValidateRect(hwnd, null_mut()); - } else { - error!("ResizeBuffers failed: 0x{:x}", res); - } + error!("ResizeBuffers failed: 0x{:x}", res); } } else { self.log_dropped_msg(hwnd, msg, wparam, lparam); @@ -980,7 +855,7 @@ impl WindowBuilder { let state = WndState { handler: self.handler.unwrap(), render_target: None, - dcomp_state: None, + dxgi_state: None, min_size: self.min_size, keyboard_state: KeyboardState::new(), captured_mouse_buttons: MouseButtons::new(), @@ -1060,67 +935,57 @@ unsafe fn choose_adapter(factory: *mut IDXGIFactory2) -> *mut IDXGIAdapter { best_adapter } -unsafe fn create_dcomp_state( +unsafe fn create_dxgi_state( present_strategy: PresentStrategy, hwnd: HWND, -) -> Result, Error> { - if present_strategy == PresentStrategy::Hwnd { - return Ok(None); - } - if let Some(create_dxgi_factory1) = OPTIONAL_FUNCTIONS.CreateDXGIFactory1 { - let mut factory: *mut IDXGIFactory2 = null_mut(); - as_result(create_dxgi_factory1( - &IID_IDXGIFactory2, - &mut factory as *mut *mut IDXGIFactory2 as *mut *mut c_void, - ))?; - debug!("dxgi factory pointer = {:?}", factory); - let adapter = choose_adapter(factory); - debug!("adapter = {:?}", adapter); - - let mut d3d11_device = D3D11Device::new_simple()?; - //let mut d2d1_device = d3d11_device.create_d2d1_device()?; - - let (swap_effect, bufs) = match present_strategy { - PresentStrategy::Hwnd => unreachable!(), - PresentStrategy::Sequential => (DXGI_SWAP_EFFECT_SEQUENTIAL, 1), - PresentStrategy::Flip | PresentStrategy::FlipRedirect => { - (DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, 2) - } - }; - let desc = DXGI_SWAP_CHAIN_DESC1 { - Width: 1024, - Height: 768, - Format: DXGI_FORMAT_B8G8R8A8_UNORM, - Stereo: FALSE, - SampleDesc: DXGI_SAMPLE_DESC { - Count: 1, - Quality: 0, - }, - BufferUsage: DXGI_USAGE_RENDER_TARGET_OUTPUT, - BufferCount: bufs, - Scaling: DXGI_SCALING_STRETCH, - SwapEffect: swap_effect, - AlphaMode: DXGI_ALPHA_MODE_IGNORE, - Flags: 0, - }; - let mut swap_chain: *mut IDXGISwapChain1 = null_mut(); - let res = (*factory).CreateSwapChainForHwnd( - d3d11_device.raw_ptr() as *mut IUnknown, - hwnd, - &desc, - null_mut(), - null_mut(), - &mut swap_chain, - ); - debug!("swap chain res = 0x{:x}, pointer = {:?}", res, swap_chain); - - Ok(Some(DCompState { - swap_chain, - sizing: false, - })) - } else { - Ok(None) - } +) -> Result, Error> { + let mut factory: *mut IDXGIFactory2 = null_mut(); + as_result(CreateDXGIFactory1( + &IID_IDXGIFactory2, + &mut factory as *mut *mut IDXGIFactory2 as *mut *mut c_void, + ))?; + debug!("dxgi factory pointer = {:?}", factory); + let adapter = choose_adapter(factory); + debug!("adapter = {:?}", adapter); + + let mut d3d11_device = D3D11Device::new_simple()?; + + let (swap_effect, bufs) = match present_strategy { + PresentStrategy::Sequential => (DXGI_SWAP_EFFECT_SEQUENTIAL, 1), + PresentStrategy::Flip | PresentStrategy::FlipRedirect => { + (DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, 2) + } + }; + let desc = DXGI_SWAP_CHAIN_DESC1 { + Width: 1024, + Height: 768, + Format: DXGI_FORMAT_B8G8R8A8_UNORM, + Stereo: FALSE, + SampleDesc: DXGI_SAMPLE_DESC { + Count: 1, + Quality: 0, + }, + BufferUsage: DXGI_USAGE_RENDER_TARGET_OUTPUT, + BufferCount: bufs, + Scaling: DXGI_SCALING_STRETCH, + SwapEffect: swap_effect, + AlphaMode: DXGI_ALPHA_MODE_IGNORE, + Flags: 0, + }; + let mut swap_chain: *mut IDXGISwapChain1 = null_mut(); + let res = (*factory).CreateSwapChainForHwnd( + d3d11_device.raw_ptr() as *mut IUnknown, + hwnd, + &desc, + null_mut(), + null_mut(), + &mut swap_chain, + ); + debug!("swap chain res = 0x{:x}, pointer = {:?}", res, swap_chain); + + Ok(Some(DxgiState { + swap_chain, + })) } #[cfg(target_arch = "x86_64")] @@ -1492,14 +1357,6 @@ impl IdleHandle { } } -/// Casts render target to hwnd variant. -unsafe fn cast_to_hwnd(dc: &DeviceContext) -> Option { - dc.get_comptr() - .cast() - .ok() - .map(|com_ptr| HwndRenderTarget::from_ptr(com_ptr)) -} - impl Default for WindowHandle { fn default() -> Self { WindowHandle {