Slightly better error handling
Handle backend initialization failure. Also actually disable vsync when it's not supported in the new xrender backend. Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
parent
72a977eed5
commit
7a446ca1f4
|
@ -25,6 +25,8 @@
|
||||||
#define auto __auto_type
|
#define auto __auto_type
|
||||||
|
|
||||||
typedef struct _xrender_data {
|
typedef struct _xrender_data {
|
||||||
|
/// If vsync is enabled and supported by the current system
|
||||||
|
bool vsync;
|
||||||
/// The idle fence for the present extension
|
/// The idle fence for the present extension
|
||||||
xcb_sync_fence_t idle_fence;
|
xcb_sync_fence_t idle_fence;
|
||||||
bool present_in_progress;
|
bool present_in_progress;
|
||||||
|
@ -393,6 +395,30 @@ static void release_win(void *backend_data, session_t *ps, win *w, void *win_dat
|
||||||
free(wd);
|
free(wd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void deinit(void *backend_data, session_t *ps) {
|
||||||
|
struct _xrender_data *xd = backend_data;
|
||||||
|
for (int i = 0; i < 256; i++) {
|
||||||
|
xcb_render_free_picture(ps->c, xd->alpha_pict[i]);
|
||||||
|
}
|
||||||
|
xcb_render_free_picture(ps->c, xd->target);
|
||||||
|
xcb_render_free_picture(ps->c, xd->root_pict);
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
xcb_render_free_picture(ps->c, xd->back[i]);
|
||||||
|
xcb_free_pixmap(ps->c, xd->back_pixmap[i]);
|
||||||
|
}
|
||||||
|
for (int i = 0; ps->o.blur_kerns[i]; i++) {
|
||||||
|
free(xd->x_blur_kern[i]);
|
||||||
|
}
|
||||||
|
if (xd->present_event) {
|
||||||
|
xcb_unregister_for_special_event(ps->c, xd->present_event);
|
||||||
|
}
|
||||||
|
xcb_render_free_picture(ps->c, xd->white_pixel);
|
||||||
|
xcb_render_free_picture(ps->c, xd->black_pixel);
|
||||||
|
xcb_render_free_picture(ps->c, xd->shadow_pixel);
|
||||||
|
free_conv(xd->shadow_kernel);
|
||||||
|
free(xd);
|
||||||
|
}
|
||||||
|
|
||||||
static void *init(session_t *ps) {
|
static void *init(session_t *ps) {
|
||||||
auto xd = ccalloc(1, struct _xrender_data);
|
auto xd = ccalloc(1, struct _xrender_data);
|
||||||
|
|
||||||
|
@ -429,13 +455,41 @@ static void *init(session_t *ps) {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xd->vsync = ps->o.vsync != VSYNC_NONE;
|
||||||
|
if (ps->present_exists) {
|
||||||
|
auto eid = xcb_generate_id(ps->c);
|
||||||
|
auto e =
|
||||||
|
xcb_request_check(ps->c, xcb_present_select_input_checked(
|
||||||
|
ps->c, eid, xd->target_win,
|
||||||
|
XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY));
|
||||||
|
if (e) {
|
||||||
|
log_error("Cannot select present input, vsync will be disabled");
|
||||||
|
xd->vsync = false;
|
||||||
|
free(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
xd->present_event =
|
||||||
|
xcb_register_for_special_xge(ps->c, &xcb_present_id, eid, NULL);
|
||||||
|
if (!xd->present_event) {
|
||||||
|
log_error("Cannot register for special XGE, vsync will be "
|
||||||
|
"disabled");
|
||||||
|
xd->vsync = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
xd->vsync = false;
|
||||||
|
}
|
||||||
|
|
||||||
// We might need to do double buffering for vsync
|
// We might need to do double buffering for vsync
|
||||||
int pixmap_needed = ps->o.vsync ? 2 : 1;
|
int pixmap_needed = xd->vsync ? 2 : 1;
|
||||||
for (int i = 0; i < pixmap_needed; i++) {
|
for (int i = 0; i < pixmap_needed; i++) {
|
||||||
xd->back_pixmap[i] = x_create_pixmap(ps->c, pictfmt->depth, ps->root,
|
xd->back_pixmap[i] = x_create_pixmap(ps->c, pictfmt->depth, ps->root,
|
||||||
ps->root_width, ps->root_height);
|
ps->root_width, ps->root_height);
|
||||||
xd->back[i] = x_create_picture_with_pictfmt_and_pixmap(
|
xd->back[i] = x_create_picture_with_pictfmt_and_pixmap(
|
||||||
ps->c, pictfmt, xd->back_pixmap[i], 0, NULL);
|
ps->c, pictfmt, xd->back_pixmap[i], 0, NULL);
|
||||||
|
if (xd->back_pixmap[i] == XCB_NONE || xd->back[i] == XCB_NONE) {
|
||||||
|
log_error("Cannot create pixmap for rendering");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
xd->curr_back = 0;
|
xd->curr_back = 0;
|
||||||
|
|
||||||
|
@ -446,41 +500,15 @@ static void *init(session_t *ps) {
|
||||||
xd->root_pict = x_create_picture_with_visual_and_pixmap(
|
xd->root_pict = x_create_picture_with_visual_and_pixmap(
|
||||||
ps->c, ps->vis, root_pixmap, 0, NULL);
|
ps->c, ps->vis, root_pixmap, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ps->present_exists) {
|
|
||||||
auto eid = xcb_generate_id(ps->c);
|
|
||||||
auto e =
|
|
||||||
xcb_request_check(ps->c, xcb_present_select_input_checked(
|
|
||||||
ps->c, eid, xd->target_win,
|
|
||||||
XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY));
|
|
||||||
if (e) {
|
|
||||||
log_error("Cannot select present input, vsync will be disabled");
|
|
||||||
free(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
xd->present_event =
|
|
||||||
xcb_register_for_special_xge(ps->c, &xcb_present_id, eid, NULL);
|
|
||||||
if (!xd->present_event) {
|
|
||||||
log_error("Cannot register for special XGE, vsync will be "
|
|
||||||
"disabled");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int i = 0; ps->o.blur_kerns[i]; i++) {
|
for (int i = 0; ps->o.blur_kerns[i]; i++) {
|
||||||
assert(i < MAX_BLUR_PASS - 1);
|
assert(i < MAX_BLUR_PASS - 1);
|
||||||
xd->x_blur_kern_size[i] = x_picture_filter_from_conv(
|
xd->x_blur_kern_size[i] = x_picture_filter_from_conv(
|
||||||
ps->o.blur_kerns[i], 1, &xd->x_blur_kern[i], (size_t[]){0});
|
ps->o.blur_kerns[i], 1, &xd->x_blur_kern[i], (size_t[]){0});
|
||||||
}
|
}
|
||||||
return xd;
|
return xd;
|
||||||
}
|
err:
|
||||||
|
deinit(xd, ps);
|
||||||
static void deinit(void *backend_data, session_t *ps) {
|
return NULL;
|
||||||
struct _xrender_data *xd = backend_data;
|
|
||||||
for (int i = 0; i < 256; i++)
|
|
||||||
xcb_render_free_picture(ps->c, xd->alpha_pict[i]);
|
|
||||||
xcb_render_free_picture(ps->c, xd->white_pixel);
|
|
||||||
xcb_render_free_picture(ps->c, xd->black_pixel);
|
|
||||||
free_conv(xd->shadow_kernel);
|
|
||||||
free(xd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *root_change(void *backend_data, session_t *ps) {
|
static void *root_change(void *backend_data, session_t *ps) {
|
||||||
|
@ -490,7 +518,7 @@ static void *root_change(void *backend_data, session_t *ps) {
|
||||||
|
|
||||||
static void prepare(void *backend_data, session_t *ps, const region_t *reg_paint) {
|
static void prepare(void *backend_data, session_t *ps, const region_t *reg_paint) {
|
||||||
struct _xrender_data *xd = backend_data;
|
struct _xrender_data *xd = backend_data;
|
||||||
if (ps->o.vsync != VSYNC_NONE && ps->present_exists && xd->present_in_progress) {
|
if (xd->vsync && xd->present_in_progress) {
|
||||||
// TODO don't block wait for present completion
|
// TODO don't block wait for present completion
|
||||||
xcb_present_generic_event_t *pev =
|
xcb_present_generic_event_t *pev =
|
||||||
(void *)xcb_wait_for_special_event(ps->c, xd->present_event);
|
(void *)xcb_wait_for_special_event(ps->c, xd->present_event);
|
||||||
|
@ -518,7 +546,7 @@ static void prepare(void *backend_data, session_t *ps, const region_t *reg_paint
|
||||||
static void present(void *backend_data, session_t *ps) {
|
static void present(void *backend_data, session_t *ps) {
|
||||||
struct _xrender_data *xd = backend_data;
|
struct _xrender_data *xd = backend_data;
|
||||||
|
|
||||||
if (ps->o.vsync != VSYNC_NONE && ps->present_exists) {
|
if (xd->vsync) {
|
||||||
// Only reset the fence when we are sure we will trigger it again.
|
// Only reset the fence when we are sure we will trigger it again.
|
||||||
// To make sure rendering won't get stuck if user toggles vsync on the
|
// To make sure rendering won't get stuck if user toggles vsync on the
|
||||||
// fly.
|
// fly.
|
||||||
|
|
|
@ -75,7 +75,7 @@ session_destroy(session_t *ps);
|
||||||
static void
|
static void
|
||||||
cxinerama_upd_scrs(session_t *ps);
|
cxinerama_upd_scrs(session_t *ps);
|
||||||
|
|
||||||
static void
|
static bool must_use
|
||||||
redir_start(session_t *ps);
|
redir_start(session_t *ps);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -657,7 +657,9 @@ paint_preprocess(session_t *ps, bool *fade_running) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ev_timer_stop(ps->loop, &ps->unredir_timer);
|
ev_timer_stop(ps->loop, &ps->unredir_timer);
|
||||||
redir_start(ps);
|
if (!redir_start(ps)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
|
@ -828,7 +830,9 @@ configure_win(session_t *ps, xcb_configure_notify_event_t *ce) {
|
||||||
// Re-redirect screen if required
|
// Re-redirect screen if required
|
||||||
if (ps->o.reredir_on_root_change && ps->redirected) {
|
if (ps->o.reredir_on_root_change && ps->redirected) {
|
||||||
redir_stop(ps);
|
redir_stop(ps);
|
||||||
redir_start(ps);
|
if (!redir_start(ps)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invalidate reg_ignore from the top
|
// Invalidate reg_ignore from the top
|
||||||
|
@ -853,6 +857,12 @@ configure_win(session_t *ps, xcb_configure_notify_event_t *ce) {
|
||||||
bi->root_change(ps->backend_data, ps);
|
bi->root_change(ps->backend_data, ps);
|
||||||
} else {
|
} else {
|
||||||
ps->backend_data = bi->init(ps);
|
ps->backend_data = bi->init(ps);
|
||||||
|
if (!ps->backend_data) {
|
||||||
|
log_fatal("Failed to re-initialize backend after root change, aborting...");
|
||||||
|
ps->quit = true;
|
||||||
|
ev_break(ps->loop, EVBREAK_ALL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
force_repaint(ps);
|
force_repaint(ps);
|
||||||
|
@ -1961,8 +1971,10 @@ init_overlay(session_t *ps) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Redirect all windows.
|
* Redirect all windows.
|
||||||
|
*
|
||||||
|
* @return whether the operation succeeded or not
|
||||||
*/
|
*/
|
||||||
static void
|
static bool
|
||||||
redir_start(session_t *ps) {
|
redir_start(session_t *ps) {
|
||||||
if (!ps->redirected) {
|
if (!ps->redirected) {
|
||||||
log_debug("Screen redirected.");
|
log_debug("Screen redirected.");
|
||||||
|
@ -1982,6 +1994,12 @@ redir_start(session_t *ps) {
|
||||||
backend_info_t *bi = backend_list[ps->o.backend];
|
backend_info_t *bi = backend_list[ps->o.backend];
|
||||||
assert(bi);
|
assert(bi);
|
||||||
ps->backend_data = bi->init(ps);
|
ps->backend_data = bi->init(ps);
|
||||||
|
if (!ps->backend_data) {
|
||||||
|
log_fatal("Failed to initialize backend, aborting...");
|
||||||
|
ps->quit = true;
|
||||||
|
ev_break(ps->loop, EVBREAK_ALL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
for (win *w = ps->list; w; w = w->next) {
|
for (win *w = ps->list; w; w = w->next) {
|
||||||
if (w->a.map_state == XCB_MAP_STATE_VIEWABLE) {
|
if (w->a.map_state == XCB_MAP_STATE_VIEWABLE) {
|
||||||
w->win_data = bi->prepare_win(ps->backend_data, ps, w);
|
w->win_data = bi->prepare_win(ps->backend_data, ps, w);
|
||||||
|
@ -2006,6 +2024,7 @@ redir_start(session_t *ps) {
|
||||||
// Repaint the whole screen
|
// Repaint the whole screen
|
||||||
force_repaint(ps);
|
force_repaint(ps);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue