diff --git a/src/backend/backend.c b/src/backend/backend.c index d9fa1bd222..f74880d134 100644 --- a/src/backend/backend.c +++ b/src/backend/backend.c @@ -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 diff --git a/src/picom.c b/src/picom.c index 9b09ca9c20..5635ef9a74 100644 --- a/src/picom.c +++ b/src/picom.c @@ -1682,6 +1682,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); @@ -1789,6 +1805,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}); @@ -1889,22 +1934,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); diff --git a/src/x.h b/src/x.h index 3a15d6d02d..5e6a98d66c 100644 --- a/src/x.h +++ b/src/x.h @@ -56,10 +56,17 @@ typedef struct pending_reply { } pending_reply_t; struct x_connection { + // Public fields + // These are part of the public ABI, changing these + // requires bumping PICOM_API_MAJOR. /// XCB connection. xcb_connection_t *c; /// Display in use. Display *dpy; + /// Default screen + int screen; + + // Private fields /// Head pointer of the error ignore linked list. pending_reply_t *pending_reply_head; /// Pointer to the next member of tail element of the error @@ -67,8 +74,6 @@ struct x_connection { pending_reply_t **pending_reply_tail; /// Previous handler of X errors XErrorHandler previous_xerror_handler; - /// Default screen - int screen; /// Information about the default screen xcb_screen_t *screen_info; };