mirror of
https://github.com/yshui/picom.git
synced 2025-04-21 18:03:02 -04:00
renderer: reset if device is lost
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
parent
6357ea0426
commit
c3883b8064
2 changed files with 45 additions and 41 deletions
|
@ -80,31 +80,6 @@ bool backend_can_present(struct backend_info *info) {
|
|||
return info->can_present;
|
||||
}
|
||||
|
||||
void handle_device_reset(session_t *ps) {
|
||||
log_error("Device reset detected");
|
||||
// Wait for reset to complete
|
||||
// Although ideally the backend should return DEVICE_STATUS_NORMAL after a reset
|
||||
// is completed, it's not always possible.
|
||||
//
|
||||
// According to ARB_robustness (emphasis mine):
|
||||
//
|
||||
// "If a reset status other than NO_ERROR is returned and subsequent
|
||||
// calls return NO_ERROR, the context reset was encountered and
|
||||
// completed. If a reset status is repeatedly returned, the context **may**
|
||||
// be in the process of resetting."
|
||||
//
|
||||
// Which means it may also not be in the process of resetting. For example on
|
||||
// AMDGPU devices, Mesa OpenGL always return CONTEXT_RESET after a reset has
|
||||
// started, completed or not.
|
||||
//
|
||||
// So here we blindly wait 5 seconds and hope ourselves best of the luck.
|
||||
sleep(5);
|
||||
|
||||
// Reset picom
|
||||
log_info("Resetting picom after device reset");
|
||||
ev_break(ps->loop, EVBREAK_ALL);
|
||||
}
|
||||
|
||||
/// Execute a list of backend commands on the backend
|
||||
/// @param target the image to render into
|
||||
/// @param root_image the image containing the desktop background
|
||||
|
|
61
src/picom.c
61
src/picom.c
|
@ -1679,6 +1679,22 @@ static void handle_pending_updates(EV_P_ struct session *ps, double delta_t) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn on the program reset flag.
|
||||
*
|
||||
* This will result in the compositor resetting itself after next paint.
|
||||
*/
|
||||
static void reset_enable(EV_P_ ev_signal *w attr_unused, int revents attr_unused) {
|
||||
log_info("picom is resetting...");
|
||||
ev_break(EV_A_ EVBREAK_ALL);
|
||||
}
|
||||
|
||||
static void exit_enable(EV_P attr_unused, ev_signal *w, int revents attr_unused) {
|
||||
session_t *ps = session_ptr(w, int_signal);
|
||||
log_info("picom is quitting...");
|
||||
quit(ps);
|
||||
}
|
||||
|
||||
static void draw_callback_impl(EV_P_ session_t *ps, int revents attr_unused) {
|
||||
assert(!ps->backend_busy);
|
||||
assert(ps->render_queued);
|
||||
|
@ -1786,6 +1802,35 @@ static void draw_callback_impl(EV_P_ session_t *ps, int revents attr_unused) {
|
|||
now = get_time_timespec();
|
||||
auto render_start_us =
|
||||
(uint64_t)now.tv_sec * 1000000UL + (uint64_t)now.tv_nsec / 1000;
|
||||
if (ps->backend_data->ops.device_status &&
|
||||
ps->backend_data->ops.device_status(ps->backend_data) !=
|
||||
DEVICE_STATUS_NORMAL) {
|
||||
log_error("Device reset detected");
|
||||
// Wait for reset to complete
|
||||
// Although ideally the backend should return
|
||||
// DEVICE_STATUS_NORMAL after a reset is completed, it's
|
||||
// not always possible.
|
||||
//
|
||||
// According to ARB_robustness (emphasis mine):
|
||||
//
|
||||
// "If a reset status other than NO_ERROR is returned
|
||||
// and subsequent calls return NO_ERROR, the context
|
||||
// reset was encountered and completed. If a reset
|
||||
// status is repeatedly returned, the context **may**
|
||||
// be in the process of resetting."
|
||||
//
|
||||
// Which means it may also not be in the process of
|
||||
// resetting. For example on AMDGPU devices, Mesa OpenGL
|
||||
// always return CONTEXT_RESET after a reset has started,
|
||||
// completed or not.
|
||||
//
|
||||
// So here we blindly wait 5 seconds and hope ourselves
|
||||
// best of the luck.
|
||||
sleep(5);
|
||||
log_info("Resetting picom after device reset");
|
||||
reset_enable(ps->loop, NULL, 0);
|
||||
return;
|
||||
}
|
||||
layout_manager_append_layout(
|
||||
ps->layout_manager, ps->wm, ps->root_image_generation,
|
||||
(ivec2){.width = ps->root_width, .height = ps->root_height});
|
||||
|
@ -1883,22 +1928,6 @@ static void x_event_callback(EV_P attr_unused, ev_io *w, int revents attr_unused
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn on the program reset flag.
|
||||
*
|
||||
* This will result in the compositor resetting itself after next paint.
|
||||
*/
|
||||
static void reset_enable(EV_P_ ev_signal *w attr_unused, int revents attr_unused) {
|
||||
log_info("picom is resetting...");
|
||||
ev_break(EV_A_ EVBREAK_ALL);
|
||||
}
|
||||
|
||||
static void exit_enable(EV_P attr_unused, ev_signal *w, int revents attr_unused) {
|
||||
session_t *ps = session_ptr(w, int_signal);
|
||||
log_info("picom is quitting...");
|
||||
quit(ps);
|
||||
}
|
||||
|
||||
static void config_file_change_cb(void *_ps) {
|
||||
auto ps = (struct session *)_ps;
|
||||
reset_enable(ps->loop, NULL, 0);
|
||||
|
|
Loading…
Add table
Reference in a new issue