QOL improvement when device lost happens
This commit is contained in:
parent
cc763729a0
commit
d194bf4f52
5 changed files with 42 additions and 14 deletions
|
@ -447,6 +447,8 @@ impl Tiling {
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default)]
|
||||||
pub(crate) struct RequestFrameOptions {
|
pub(crate) struct RequestFrameOptions {
|
||||||
pub(crate) require_presentation: bool,
|
pub(crate) require_presentation: bool,
|
||||||
|
/// Force refresh of all rendering states when true
|
||||||
|
pub(crate) force_render: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) trait PlatformWindow: HasWindowHandle + HasDisplayHandle {
|
pub(crate) trait PlatformWindow: HasWindowHandle + HasDisplayHandle {
|
||||||
|
|
|
@ -22,7 +22,7 @@ use crate::{
|
||||||
*,
|
*,
|
||||||
};
|
};
|
||||||
|
|
||||||
const DISABLE_DIRECT_COMPOSITION: &str = "GPUI_DISABLE_DIRECT_COMPOSITION";
|
pub(crate) const DISABLE_DIRECT_COMPOSITION: &str = "GPUI_DISABLE_DIRECT_COMPOSITION";
|
||||||
const RENDER_TARGET_FORMAT: DXGI_FORMAT = DXGI_FORMAT_B8G8R8A8_UNORM;
|
const RENDER_TARGET_FORMAT: DXGI_FORMAT = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||||
// This configuration is used for MSAA rendering on paths only, and it's guaranteed to be supported by DirectX 11.
|
// This configuration is used for MSAA rendering on paths only, and it's guaranteed to be supported by DirectX 11.
|
||||||
const PATH_MULTISAMPLE_COUNT: u32 = 4;
|
const PATH_MULTISAMPLE_COUNT: u32 = 4;
|
||||||
|
@ -113,9 +113,7 @@ impl DirectXDevices {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DirectXRenderer {
|
impl DirectXRenderer {
|
||||||
pub(crate) fn new(hwnd: HWND) -> Result<Self> {
|
pub(crate) fn new(hwnd: HWND, disable_direct_composition: bool) -> Result<Self> {
|
||||||
let disable_direct_composition = std::env::var(DISABLE_DIRECT_COMPOSITION)
|
|
||||||
.is_ok_and(|value| value == "true" || value == "1");
|
|
||||||
if disable_direct_composition {
|
if disable_direct_composition {
|
||||||
log::info!("Direct Composition is disabled.");
|
log::info!("Direct Composition is disabled.");
|
||||||
}
|
}
|
||||||
|
@ -198,6 +196,9 @@ impl DirectXRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_device_lost(&mut self) -> Result<()> {
|
fn handle_device_lost(&mut self) -> Result<()> {
|
||||||
|
// Here we wait a bit to ensure the the system has time to recover from the device lost state.
|
||||||
|
// If we don't wait, the final drawing result will be blank.
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(300));
|
||||||
let disable_direct_composition = self.direct_composition.is_none();
|
let disable_direct_composition = self.direct_composition.is_none();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -323,6 +324,8 @@ impl DirectXRenderer {
|
||||||
"DirectX device removed or reset when resizing. Reason: {:?}",
|
"DirectX device removed or reset when resizing. Reason: {:?}",
|
||||||
reason
|
reason
|
||||||
);
|
);
|
||||||
|
self.resources.width = width;
|
||||||
|
self.resources.height = height;
|
||||||
self.handle_device_lost()?;
|
self.handle_device_lost()?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ pub(crate) const WM_GPUI_CURSOR_STYLE_CHANGED: u32 = WM_USER + 1;
|
||||||
pub(crate) const WM_GPUI_CLOSE_ONE_WINDOW: u32 = WM_USER + 2;
|
pub(crate) const WM_GPUI_CLOSE_ONE_WINDOW: u32 = WM_USER + 2;
|
||||||
pub(crate) const WM_GPUI_TASK_DISPATCHED_ON_MAIN_THREAD: u32 = WM_USER + 3;
|
pub(crate) const WM_GPUI_TASK_DISPATCHED_ON_MAIN_THREAD: u32 = WM_USER + 3;
|
||||||
pub(crate) const WM_GPUI_DOCK_MENU_ACTION: u32 = WM_USER + 4;
|
pub(crate) const WM_GPUI_DOCK_MENU_ACTION: u32 = WM_USER + 4;
|
||||||
|
pub(crate) const WM_GPUI_FORCE_UPDATE_WINDOW: u32 = WM_USER + 5;
|
||||||
|
|
||||||
const SIZE_MOVE_LOOP_TIMER_ID: usize = 1;
|
const SIZE_MOVE_LOOP_TIMER_ID: usize = 1;
|
||||||
const AUTO_HIDE_TASKBAR_THICKNESS_PX: i32 = 1;
|
const AUTO_HIDE_TASKBAR_THICKNESS_PX: i32 = 1;
|
||||||
|
@ -97,6 +98,7 @@ pub(crate) fn handle_msg(
|
||||||
WM_SETTINGCHANGE => handle_system_settings_changed(handle, wparam, lparam, state_ptr),
|
WM_SETTINGCHANGE => handle_system_settings_changed(handle, wparam, lparam, state_ptr),
|
||||||
WM_INPUTLANGCHANGE => handle_input_language_changed(lparam, state_ptr),
|
WM_INPUTLANGCHANGE => handle_input_language_changed(lparam, state_ptr),
|
||||||
WM_GPUI_CURSOR_STYLE_CHANGED => handle_cursor_changed(lparam, state_ptr),
|
WM_GPUI_CURSOR_STYLE_CHANGED => handle_cursor_changed(lparam, state_ptr),
|
||||||
|
WM_GPUI_FORCE_UPDATE_WINDOW => draw_window(handle, true, state_ptr),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
if let Some(n) = handled {
|
if let Some(n) = handled {
|
||||||
|
@ -1202,6 +1204,19 @@ fn handle_device_change_msg(
|
||||||
state_ptr: Rc<WindowsWindowStatePtr>,
|
state_ptr: Rc<WindowsWindowStatePtr>,
|
||||||
) -> Option<isize> {
|
) -> Option<isize> {
|
||||||
if wparam.0 == DBT_DEVNODES_CHANGED as usize {
|
if wparam.0 == DBT_DEVNODES_CHANGED as usize {
|
||||||
|
// The reason for sending this message is to actually trigger a redraw of the window.
|
||||||
|
unsafe {
|
||||||
|
PostMessageW(
|
||||||
|
Some(handle),
|
||||||
|
WM_GPUI_FORCE_UPDATE_WINDOW,
|
||||||
|
WPARAM(0),
|
||||||
|
LPARAM(0),
|
||||||
|
)
|
||||||
|
.log_err();
|
||||||
|
}
|
||||||
|
// If the GPU device is lost, this redraw will take care of recreating the device context.
|
||||||
|
// The WM_GPUI_FORCE_UPDATE_WINDOW message will take care of redrawing the window, after
|
||||||
|
// the device context has been recreated.
|
||||||
draw_window(handle, true, state_ptr)
|
draw_window(handle, true, state_ptr)
|
||||||
} else {
|
} else {
|
||||||
// Other device change messages are not handled.
|
// Other device change messages are not handled.
|
||||||
|
@ -1212,7 +1227,7 @@ fn handle_device_change_msg(
|
||||||
#[inline]
|
#[inline]
|
||||||
fn draw_window(
|
fn draw_window(
|
||||||
handle: HWND,
|
handle: HWND,
|
||||||
force_draw: bool,
|
force_render: bool,
|
||||||
state_ptr: Rc<WindowsWindowStatePtr>,
|
state_ptr: Rc<WindowsWindowStatePtr>,
|
||||||
) -> Option<isize> {
|
) -> Option<isize> {
|
||||||
let mut request_frame = state_ptr
|
let mut request_frame = state_ptr
|
||||||
|
@ -1222,7 +1237,8 @@ fn draw_window(
|
||||||
.request_frame
|
.request_frame
|
||||||
.take()?;
|
.take()?;
|
||||||
request_frame(RequestFrameOptions {
|
request_frame(RequestFrameOptions {
|
||||||
require_presentation: force_draw,
|
require_presentation: false,
|
||||||
|
force_render,
|
||||||
});
|
});
|
||||||
state_ptr.state.borrow_mut().callbacks.request_frame = Some(request_frame);
|
state_ptr.state.borrow_mut().callbacks.request_frame = Some(request_frame);
|
||||||
unsafe { ValidateRect(Some(handle), None).ok().log_err() };
|
unsafe { ValidateRect(Some(handle), None).ok().log_err() };
|
||||||
|
|
|
@ -84,6 +84,7 @@ impl WindowsWindowState {
|
||||||
display: WindowsDisplay,
|
display: WindowsDisplay,
|
||||||
min_size: Option<Size<Pixels>>,
|
min_size: Option<Size<Pixels>>,
|
||||||
appearance: WindowAppearance,
|
appearance: WindowAppearance,
|
||||||
|
disable_direct_composition: bool,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let scale_factor = {
|
let scale_factor = {
|
||||||
let monitor_dpi = unsafe { GetDpiForWindow(hwnd) } as f32;
|
let monitor_dpi = unsafe { GetDpiForWindow(hwnd) } as f32;
|
||||||
|
@ -100,7 +101,7 @@ impl WindowsWindowState {
|
||||||
};
|
};
|
||||||
let border_offset = WindowBorderOffset::default();
|
let border_offset = WindowBorderOffset::default();
|
||||||
let restore_from_minimized = None;
|
let restore_from_minimized = None;
|
||||||
let renderer = DirectXRenderer::new(hwnd)?;
|
let renderer = DirectXRenderer::new(hwnd, disable_direct_composition)?;
|
||||||
let callbacks = Callbacks::default();
|
let callbacks = Callbacks::default();
|
||||||
let input_handler = None;
|
let input_handler = None;
|
||||||
let pending_surrogate = None;
|
let pending_surrogate = None;
|
||||||
|
@ -208,6 +209,7 @@ impl WindowsWindowStatePtr {
|
||||||
context.display,
|
context.display,
|
||||||
context.min_size,
|
context.min_size,
|
||||||
context.appearance,
|
context.appearance,
|
||||||
|
context.disable_direct_composition,
|
||||||
)?);
|
)?);
|
||||||
|
|
||||||
Ok(Rc::new_cyclic(|this| Self {
|
Ok(Rc::new_cyclic(|this| Self {
|
||||||
|
@ -339,6 +341,7 @@ struct WindowCreateContext {
|
||||||
main_receiver: flume::Receiver<Runnable>,
|
main_receiver: flume::Receiver<Runnable>,
|
||||||
main_thread_id_win32: u32,
|
main_thread_id_win32: u32,
|
||||||
appearance: WindowAppearance,
|
appearance: WindowAppearance,
|
||||||
|
disable_direct_composition: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WindowsWindow {
|
impl WindowsWindow {
|
||||||
|
@ -371,17 +374,20 @@ impl WindowsWindow {
|
||||||
.map(|title| title.as_ref())
|
.map(|title| title.as_ref())
|
||||||
.unwrap_or(""),
|
.unwrap_or(""),
|
||||||
);
|
);
|
||||||
let (dwexstyle, mut dwstyle) = if params.kind == WindowKind::PopUp {
|
let disable_direct_composition = std::env::var(DISABLE_DIRECT_COMPOSITION)
|
||||||
(
|
.is_ok_and(|value| value == "true" || value == "1");
|
||||||
WS_EX_TOOLWINDOW | WS_EX_NOREDIRECTIONBITMAP,
|
|
||||||
WINDOW_STYLE(0x0),
|
let (mut dwexstyle, dwstyle) = if params.kind == WindowKind::PopUp {
|
||||||
)
|
(WS_EX_TOOLWINDOW, WINDOW_STYLE(0x0))
|
||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
WS_EX_APPWINDOW | WS_EX_NOREDIRECTIONBITMAP,
|
WS_EX_APPWINDOW,
|
||||||
WS_THICKFRAME | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX,
|
WS_THICKFRAME | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
if !disable_direct_composition {
|
||||||
|
dwexstyle |= WS_EX_NOREDIRECTIONBITMAP;
|
||||||
|
}
|
||||||
|
|
||||||
let hinstance = get_module_handle();
|
let hinstance = get_module_handle();
|
||||||
let display = if let Some(display_id) = params.display_id {
|
let display = if let Some(display_id) = params.display_id {
|
||||||
|
@ -406,6 +412,7 @@ impl WindowsWindow {
|
||||||
main_receiver,
|
main_receiver,
|
||||||
main_thread_id_win32,
|
main_thread_id_win32,
|
||||||
appearance,
|
appearance,
|
||||||
|
disable_direct_composition,
|
||||||
};
|
};
|
||||||
let lpparam = Some(&context as *const _ as *const _);
|
let lpparam = Some(&context as *const _ as *const _);
|
||||||
let creation_result = unsafe {
|
let creation_result = unsafe {
|
||||||
|
|
|
@ -1020,7 +1020,7 @@ impl Window {
|
||||||
|| (active.get()
|
|| (active.get()
|
||||||
&& last_input_timestamp.get().elapsed() < Duration::from_secs(1));
|
&& last_input_timestamp.get().elapsed() < Duration::from_secs(1));
|
||||||
|
|
||||||
if invalidator.is_dirty() {
|
if invalidator.is_dirty() || request_frame_options.force_render {
|
||||||
measure("frame duration", || {
|
measure("frame duration", || {
|
||||||
handle
|
handle
|
||||||
.update(&mut cx, |_, window, cx| {
|
.update(&mut cx, |_, window, cx| {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue