Skip to content

Commit

Permalink
core: isolate X connection with error handling into a struct
Browse files Browse the repository at this point in the history
Part of the long running effort to reduce the prevalence of `session_t`.
After this, functions that communicate with X can make use of the error
handling machinary (set_ignore_cookie, set_cant_fail_cookie) without
needing to take a `session_t` parameter.

This commit converts everything to use the new struct `x_connection`,
most of the conversions are mechanical.

Signed-off-by: Yuxuan Shui <[email protected]>
  • Loading branch information
yshui committed Jun 29, 2023
1 parent d4f7282 commit 11a091c
Show file tree
Hide file tree
Showing 23 changed files with 1,100 additions and 977 deletions.
8 changes: 4 additions & 4 deletions src/backend/backend.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,10 @@ void paint_all_new(session_t *ps, struct managed_win *t) {
return handle_device_reset(ps);
}
if (ps->o.xrender_sync_fence) {
if (ps->xsync_exists && !x_fence_sync(ps->c, ps->sync_fence)) {
if (ps->xsync_exists && !x_fence_sync(&ps->c, ps->sync_fence)) {
log_error("x_fence_sync failed, xrender-sync-fence will be "
"disabled from now on.");
xcb_sync_destroy_fence(ps->c, ps->sync_fence);
xcb_sync_destroy_fence(ps->c.c, ps->sync_fence);
ps->sync_fence = XCB_NONE;
ps->o.xrender_sync_fence = false;
ps->xsync_exists = false;
Expand Down Expand Up @@ -348,7 +348,7 @@ void paint_all_new(session_t *ps, struct managed_win *t) {
}

if (ps->o.crop_shadow_to_monitor && w->randr_monitor >= 0 &&
w->randr_monitor < ps->randr_nmonitors) {
w->randr_monitor < ps->monitors.count) {
// There can be a window where number of monitors is
// updated, but the monitor number attached to the window
// have not.
Expand All @@ -358,7 +358,7 @@ void paint_all_new(session_t *ps, struct managed_win *t) {
// bounds.
pixman_region32_intersect(
&reg_shadow, &reg_shadow,
&ps->randr_monitor_regs[w->randr_monitor]);
&ps->monitors.regions[w->randr_monitor]);
}

if (ps->o.transparent_clipping) {
Expand Down
3 changes: 1 addition & 2 deletions src/backend/backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ struct backend_operations;

typedef struct backend_base {
struct backend_operations *ops;
xcb_connection_t *c;
xcb_window_t root;
struct x_connection *c;
struct ev_loop *loop;

/// Whether the backend can accept new render request at the moment
Expand Down
71 changes: 36 additions & 35 deletions src/backend/backend_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,26 @@
/**
* Generate a 1x1 <code>Picture</code> of a particular color.
*/
xcb_render_picture_t solid_picture(xcb_connection_t *c, xcb_drawable_t d, bool argb,
double a, double r, double g, double b) {
xcb_render_picture_t
solid_picture(struct x_connection *c, bool argb, double a, double r, double g, double b) {
xcb_pixmap_t pixmap;
xcb_render_picture_t picture;
xcb_render_create_picture_value_list_t pa;
xcb_render_color_t col;
xcb_rectangle_t rect;

pixmap = x_create_pixmap(c, argb ? 32 : 8, d, 1, 1);
if (!pixmap)
pixmap = x_create_pixmap(c, argb ? 32 : 8, 1, 1);
if (!pixmap) {
return XCB_NONE;
}

pa.repeat = 1;
picture = x_create_picture_with_standard_and_pixmap(
c, argb ? XCB_PICT_STANDARD_ARGB_32 : XCB_PICT_STANDARD_A_8, pixmap,
XCB_RENDER_CP_REPEAT, &pa);

if (!picture) {
xcb_free_pixmap(c, pixmap);
xcb_free_pixmap(c->c, pixmap);
return XCB_NONE;
}

Expand All @@ -51,14 +52,14 @@ xcb_render_picture_t solid_picture(xcb_connection_t *c, xcb_drawable_t d, bool a
rect.width = 1;
rect.height = 1;

xcb_render_fill_rectangles(c, XCB_RENDER_PICT_OP_SRC, picture, col, 1, &rect);
xcb_free_pixmap(c, pixmap);
xcb_render_fill_rectangles(c->c, XCB_RENDER_PICT_OP_SRC, picture, col, 1, &rect);
xcb_free_pixmap(c->c, pixmap);

return picture;
}

xcb_image_t *
make_shadow(xcb_connection_t *c, const conv *kernel, double opacity, int width, int height) {
xcb_image_t *make_shadow(struct x_connection *c, const conv *kernel, double opacity,
int width, int height) {
/*
* We classify shadows into 4 kinds of regions
* r = shadow radius
Expand All @@ -84,8 +85,9 @@ make_shadow(xcb_connection_t *c, const conv *kernel, double opacity, int width,
assert(d % 2 == 1);
assert(d > 0);

ximage = xcb_image_create_native(c, to_u16_checked(swidth), to_u16_checked(sheight),
XCB_IMAGE_FORMAT_Z_PIXMAP, 8, 0, 0, NULL);
ximage =
xcb_image_create_native(c->c, to_u16_checked(swidth), to_u16_checked(sheight),
XCB_IMAGE_FORMAT_Z_PIXMAP, 8, 0, 0, NULL);
if (!ximage) {
log_error("failed to create an X image");
return 0;
Expand Down Expand Up @@ -193,7 +195,7 @@ make_shadow(xcb_connection_t *c, const conv *kernel, double opacity, int width,
/**
* Generate shadow <code>Picture</code> for a window.
*/
bool build_shadow(xcb_connection_t *c, xcb_drawable_t d, double opacity, const int width,
bool build_shadow(struct x_connection *c, double opacity, const int width,
const int height, const conv *kernel, xcb_render_picture_t shadow_pixel,
xcb_pixmap_t *pixmap, xcb_render_picture_t *pict) {
xcb_image_t *shadow_image = NULL;
Expand All @@ -207,9 +209,9 @@ bool build_shadow(xcb_connection_t *c, xcb_drawable_t d, double opacity, const i
return false;
}

shadow_pixmap = x_create_pixmap(c, 8, d, shadow_image->width, shadow_image->height);
shadow_pixmap = x_create_pixmap(c, 8, shadow_image->width, shadow_image->height);
shadow_pixmap_argb =
x_create_pixmap(c, 32, d, shadow_image->width, shadow_image->height);
x_create_pixmap(c, 32, shadow_image->width, shadow_image->height);

if (!shadow_pixmap || !shadow_pixmap_argb) {
log_error("Failed to create shadow pixmaps");
Expand All @@ -225,11 +227,11 @@ bool build_shadow(xcb_connection_t *c, xcb_drawable_t d, double opacity, const i
}

gc = x_new_id(c);
xcb_create_gc(c, gc, shadow_pixmap, 0, NULL);
xcb_create_gc(c->c, gc, shadow_pixmap, 0, NULL);

// We need to make room for protocol metadata in the request. The metadata should
// be 24 bytes plus padding, let's be generous and give it 1kb
auto maximum_image_size = xcb_get_maximum_request_length(c) * 4 - 1024;
auto maximum_image_size = xcb_get_maximum_request_length(c->c) * 4 - 1024;
auto maximum_row =
to_u16_checked(clamp(maximum_image_size / shadow_image->stride, 0, UINT16_MAX));
if (maximum_row <= 0) {
Expand All @@ -248,23 +250,23 @@ bool build_shadow(xcb_connection_t *c, xcb_drawable_t d, double opacity, const i
}

uint32_t offset = row * shadow_image->stride / sizeof(*shadow_image->data);
xcb_put_image(c, (uint8_t)shadow_image->format, shadow_pixmap, gc,
xcb_put_image(c->c, (uint8_t)shadow_image->format, shadow_pixmap, gc,
shadow_image->width, batch_height, 0, to_i16_checked(row),
0, shadow_image->depth, shadow_image->stride * batch_height,
shadow_image->data + offset);
}

xcb_render_composite(c, XCB_RENDER_PICT_OP_SRC, shadow_pixel, shadow_picture,
xcb_render_composite(c->c, XCB_RENDER_PICT_OP_SRC, shadow_pixel, shadow_picture,
shadow_picture_argb, 0, 0, 0, 0, 0, 0, shadow_image->width,
shadow_image->height);

*pixmap = shadow_pixmap_argb;
*pict = shadow_picture_argb;

xcb_free_gc(c, gc);
xcb_free_gc(c->c, gc);
xcb_image_destroy(shadow_image);
xcb_free_pixmap(c, shadow_pixmap);
xcb_render_free_picture(c, shadow_picture);
xcb_free_pixmap(c->c, shadow_pixmap);
x_free_picture(c, shadow_picture);

return true;

Expand All @@ -273,19 +275,19 @@ bool build_shadow(xcb_connection_t *c, xcb_drawable_t d, double opacity, const i
xcb_image_destroy(shadow_image);
}
if (shadow_pixmap) {
xcb_free_pixmap(c, shadow_pixmap);
xcb_free_pixmap(c->c, shadow_pixmap);
}
if (shadow_pixmap_argb) {
xcb_free_pixmap(c, shadow_pixmap_argb);
xcb_free_pixmap(c->c, shadow_pixmap_argb);
}
if (shadow_picture) {
xcb_render_free_picture(c, shadow_picture);
x_free_picture(c, shadow_picture);
}
if (shadow_picture_argb) {
xcb_render_free_picture(c, shadow_picture_argb);
x_free_picture(c, shadow_picture_argb);
}
if (gc) {
xcb_free_gc(c, gc);
xcb_free_gc(c->c, gc);
}

return false;
Expand All @@ -294,22 +296,22 @@ bool build_shadow(xcb_connection_t *c, xcb_drawable_t d, double opacity, const i
void *default_backend_render_shadow(backend_t *backend_data, int width, int height,
struct backend_shadow_context *sctx, struct color color) {
const conv *kernel = (void *)sctx;
xcb_render_picture_t shadow_pixel = solid_picture(
backend_data->c, backend_data->root, true, 1, color.red, color.green, color.blue);
xcb_render_picture_t shadow_pixel =
solid_picture(backend_data->c, true, 1, color.red, color.green, color.blue);
xcb_pixmap_t shadow = XCB_NONE;
xcb_render_picture_t pict = XCB_NONE;

if (!build_shadow(backend_data->c, backend_data->root, color.alpha, width, height,
kernel, shadow_pixel, &shadow, &pict)) {
xcb_render_free_picture(backend_data->c, shadow_pixel);
if (!build_shadow(backend_data->c, color.alpha, width, height, kernel,
shadow_pixel, &shadow, &pict)) {
x_free_picture(backend_data->c, shadow_pixel);
return NULL;
}

auto visual = x_get_visual_for_standard(backend_data->c, XCB_PICT_STANDARD_ARGB_32);
void *ret = backend_data->ops->bind_pixmap(
backend_data, shadow, x_get_visual_info(backend_data->c, visual), true);
xcb_render_free_picture(backend_data->c, pict);
xcb_render_free_picture(backend_data->c, shadow_pixel);
x_free_picture(backend_data->c, pict);
x_free_picture(backend_data->c, shadow_pixel);
return ret;
}

Expand Down Expand Up @@ -506,9 +508,8 @@ struct backend_image *default_new_backend_image(int w, int h) {
}

void init_backend_base(struct backend_base *base, session_t *ps) {
base->c = ps->c;
base->c = &ps->c;
base->loop = ps->loop;
base->root = ps->root;
base->busy = false;
base->ops = NULL;
}
12 changes: 6 additions & 6 deletions src/backend/backend_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,15 @@ struct backend_image {
int border_width;
};

bool build_shadow(xcb_connection_t *, xcb_drawable_t, double opacity, int width,
int height, const conv *kernel, xcb_render_picture_t shadow_pixel,
bool build_shadow(struct x_connection *, double opacity, int width, int height,
const conv *kernel, xcb_render_picture_t shadow_pixel,
xcb_pixmap_t *pixmap, xcb_render_picture_t *pict);

xcb_render_picture_t solid_picture(xcb_connection_t *, xcb_drawable_t, bool argb,
double a, double r, double g, double b);
xcb_render_picture_t
solid_picture(struct x_connection *, bool argb, double a, double r, double g, double b);

xcb_image_t *
make_shadow(xcb_connection_t *c, const conv *kernel, double opacity, int width, int height);
xcb_image_t *make_shadow(struct x_connection *c, const conv *kernel, double opacity,
int width, int height);

/// The default implementation of `is_win_transparent`, it simply looks at win::mode. So
/// this is not suitable for backends that alter the content of windows
Expand Down
7 changes: 3 additions & 4 deletions src/backend/dummy/dummy.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,8 @@ struct dummy_data {

struct backend_base *dummy_init(struct session *ps attr_unused) {
auto ret = (struct backend_base *)ccalloc(1, struct dummy_data);
ret->c = ps->c;
ret->c = &ps->c;
ret->loop = ps->loop;
ret->root = ps->root;
ret->busy = false;
return ret;
}
Expand All @@ -44,7 +43,7 @@ void dummy_deinit(struct backend_base *data) {
HASH_DEL(dummy->images, img);
free(img->refcount);
if (img->owned) {
xcb_free_pixmap(data->c, img->pixmap);
xcb_free_pixmap(data->c->c, img->pixmap);
}
free(img);
}
Expand Down Expand Up @@ -118,7 +117,7 @@ void dummy_release_image(backend_t *base, void *image) {
HASH_DEL(dummy->images, img);
free(img->refcount);
if (img->owned) {
xcb_free_pixmap(base->c, img->pixmap);
xcb_free_pixmap(base->c->c, img->pixmap);
}
free(img);
}
Expand Down
13 changes: 7 additions & 6 deletions src/backend/gl/egl.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ static void egl_release_image(backend_t *base, struct gl_texture *tex) {
}

if (p->owned) {
xcb_free_pixmap(base->c, p->pixmap);
xcb_free_pixmap(base->c->c, p->pixmap);
p->pixmap = XCB_NONE;
}

Expand Down Expand Up @@ -154,10 +154,10 @@ static backend_t *egl_init(session_t *ps) {
}

gd = ccalloc(1, struct egl_data);
gd->display = eglGetPlatformDisplayProc(EGL_PLATFORM_X11_EXT, ps->dpy,
gd->display = eglGetPlatformDisplayProc(EGL_PLATFORM_X11_EXT, ps->c.dpy,
(EGLAttrib[]){
EGL_PLATFORM_X11_SCREEN_EXT,
ps->scr,
ps->c.screen,
EGL_NONE,
});
if (gd->display == EGL_NO_DISPLAY) {
Expand Down Expand Up @@ -190,7 +190,7 @@ static backend_t *egl_init(session_t *ps) {
goto end;
}

auto visual_info = x_get_visual_info(ps->c, ps->vis);
auto visual_info = x_get_visual_info(&ps->c, ps->c.screen_info->root_visual);
EGLConfig config = NULL;
int nconfigs = 1;
// clang-format off
Expand Down Expand Up @@ -280,7 +280,8 @@ egl_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, b
struct egl_data *gd = (void *)base;
struct egl_pixmap *eglpixmap = NULL;

auto r = xcb_get_geometry_reply(base->c, xcb_get_geometry(base->c, pixmap), NULL);
auto r =
xcb_get_geometry_reply(base->c->c, xcb_get_geometry(base->c->c, pixmap), NULL);
if (!r) {
log_error("Invalid pixmap %#010x", pixmap);
return NULL;
Expand Down Expand Up @@ -335,7 +336,7 @@ egl_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, b
free(eglpixmap);

if (owned) {
xcb_free_pixmap(base->c, pixmap);
xcb_free_pixmap(base->c->c, pixmap);
}
free(wd);
return NULL;
Expand Down
Loading

0 comments on commit 11a091c

Please sign in to comment.