From 01e71590e069b785014939da08fb558d588c94f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 22 Sep 2019 11:46:46 +0200 Subject: [PATCH] bar: don't use cairo This is trivial in the Wayland backend; just instantiate a pixman pointing to the same mmapped memory as the wayland buffer. In the XCB backend, we change the implementation slightly; instead of rendering via a cairo XCB surface backend (to a server side pixmap), which is then blitted to the window in commit(), we now render to a client-side pixman pixmap, and blit it using xcb_put_image() in commit(). --- bar/backend.h | 3 +- bar/bar.c | 14 ++------ bar/private.h | 17 +--------- bar/wayland.c | 89 ++++++++++++++----------------------------------- bar/xcb.c | 91 ++++++++++++++++----------------------------------- 5 files changed, 58 insertions(+), 156 deletions(-) diff --git a/bar/backend.h b/bar/backend.h index 782bb98..f2681a8 100644 --- a/bar/backend.h +++ b/bar/backend.h @@ -11,8 +11,7 @@ struct backend { void (*expose)(const struct bar *bar), void (*on_mouse)(struct bar *bar, enum mouse_event event, int x, int y)); - pixman_image_t *(*get_pixman_image)(const struct bar *bar); - void (*commit_pixman)(const struct bar *bar, pixman_image_t *pix); + void (*commit)(const struct bar *bar); void (*refresh)(const struct bar *bar); void (*set_cursor)(struct bar *bar, const char *cursor); }; diff --git a/bar/bar.c b/bar/bar.c index be048a3..19ea36d 100644 --- a/bar/bar.c +++ b/bar/bar.c @@ -61,7 +61,7 @@ static void expose(const struct bar *_bar) { const struct private *bar = _bar->private; - pixman_image_t *pix = bar->backend.iface->get_pixman_image(_bar); + pixman_image_t *pix = bar->pix; pixman_image_fill_rectangles( PIXMAN_OP_SRC, pix, &bar->background, 1, @@ -138,7 +138,7 @@ expose(const struct bar *_bar) x += bar->left_spacing + e->width + bar->right_spacing; } - bar->backend.iface->commit_pixman(_bar, pix); + bar->backend.iface->commit(_bar); } @@ -299,14 +299,6 @@ run(struct bar *_bar) bar->backend.iface->cleanup(_bar); - if (bar->cairo) - cairo_destroy(bar->cairo); - if (bar->cairo_surface) { - cairo_device_finish(cairo_surface_get_device(bar->cairo_surface)); - cairo_surface_finish(bar->cairo_surface); - cairo_surface_destroy(bar->cairo_surface); - } - LOG_DBG("bar exiting"); return ret; } @@ -341,8 +333,6 @@ destroy(struct bar *bar) m->destroy(m); } - cairo_debug_reset_static_data(); - free(b->left.mods); free(b->left.exps); free(b->center.mods); diff --git a/bar/private.h b/bar/private.h index c41d4a7..5b9aa2f 100644 --- a/bar/private.h +++ b/bar/private.h @@ -1,8 +1,5 @@ #pragma once -#include -#include - #include "../bar/bar.h" #include "backend.h" @@ -46,22 +43,10 @@ struct private { /* Name of currently active cursor */ char *cursor_name; - cairo_t *cairo; - cairo_surface_t *cairo_surface; + pixman_image_t *pix; struct { void *data; const struct backend *iface; } backend; -#if 0 - /* Backend specifics */ - xcb_connection_t *conn; - - xcb_window_t win; - xcb_colormap_t colormap; - xcb_pixmap_t pixmap; - xcb_gc_t gc; - xcb_cursor_context_t *cursor_ctx; - xcb_cursor_t cursor; -#endif }; diff --git a/bar/wayland.c b/bar/wayland.c index 4e65bf2..a8d14c9 100644 --- a/bar/wayland.c +++ b/bar/wayland.c @@ -10,7 +10,8 @@ #include #include -#include +//#include +#include #include #include @@ -21,6 +22,7 @@ #define LOG_ENABLE_DBG 0 #include "../log.h" #include "../tllist.h" +#include "../stride.h" #include "private.h" @@ -31,8 +33,7 @@ struct buffer { struct wl_buffer *wl_buf; - cairo_surface_t *cairo_surface; - cairo_t *cairo; + pixman_image_t *pix; }; struct monitor { @@ -448,11 +449,10 @@ get_buffer(struct wayland_backend *backend) * No existing buffer available. Create a new one by: * * 1. open a memory backed "file" with memfd_create() - * 2. mmap() the memory file, to be used by the cairo surface + * 2. mmap() the memory file, to be used by the pixman image * 3. create a wayland shm buffer for the same memory file * - * The cairo surface and the wayland buffer are now sharing - * memory. + * The pixman image and the wayland buffer are now sharing memory. */ int pool_fd = -1; @@ -462,8 +462,7 @@ get_buffer(struct wayland_backend *backend) struct wl_shm_pool *pool = NULL; struct wl_buffer *buf = NULL; - cairo_surface_t *cairo_surface = NULL; - cairo_t *cairo = NULL; + pixman_image_t *pix = NULL; /* Backing memory for SHM */ pool_fd = memfd_create("f00bar-wayland-shm-buffer-pool", MFD_CLOEXEC); @@ -473,8 +472,9 @@ get_buffer(struct wayland_backend *backend) } /* Total size */ - const uint32_t stride = cairo_format_stride_for_width( - CAIRO_FORMAT_ARGB32, backend->width); + const uint32_t stride = stride_for_format_and_width( + PIXMAN_a8r8g8b8, backend->width); + size = stride * backend->height; if (ftruncate(pool_fd, size) == -1) { LOG_ERR("failed to truncate SHM pool"); @@ -504,19 +504,10 @@ get_buffer(struct wayland_backend *backend) wl_shm_pool_destroy(pool); pool = NULL; close(pool_fd); pool_fd = -1; - /* Create a cairo surface around the mmapped memory */ - cairo_surface = cairo_image_surface_create_for_data( - mmapped, CAIRO_FORMAT_ARGB32, backend->width, backend->height, stride); - if (cairo_surface_status(cairo_surface) != CAIRO_STATUS_SUCCESS) { - LOG_ERR("failed to create cairo surface: %s", - cairo_status_to_string(cairo_surface_status(cairo_surface))); - goto err; - } - - cairo = cairo_create(cairo_surface); - if (cairo_status(cairo) != CAIRO_STATUS_SUCCESS) { - LOG_ERR("failed to create cairo context: %s", - cairo_status_to_string(cairo_status(cairo))); + pix = pixman_image_create_bits_no_clear( + PIXMAN_a8r8g8b8, backend->width, backend->height, (uint32_t *)mmapped, stride); + if (pix == NULL) { + LOG_ERR("failed to create pixman image"); goto err; } @@ -528,9 +519,8 @@ get_buffer(struct wayland_backend *backend) .size = size, .mmapped = mmapped, .wl_buf = buf, - .cairo_surface = cairo_surface, - .cairo = cairo} - ) + .pix = pix, + }) ); struct buffer *ret = &tll_back(backend->buffers); @@ -538,10 +528,8 @@ get_buffer(struct wayland_backend *backend) return ret; err: - if (cairo != NULL) - cairo_destroy(cairo); - if (cairo_surface != NULL) - cairo_surface_destroy(cairo_surface); + if (pix != NULL) + pixman_image_unref(pix); if (buf != NULL) wl_buffer_destroy(buf); if (pool != NULL) @@ -712,9 +700,7 @@ setup(struct bar *_bar) /* Prepare a buffer + cairo context for bar to draw to */ backend->next_buffer = get_buffer(backend); assert(backend->next_buffer != NULL && backend->next_buffer->busy); - - bar->cairo_surface = backend->next_buffer->cairo_surface; - bar->cairo = backend->next_buffer->cairo; + bar->pix = backend->next_buffer->pix; return true; } @@ -728,10 +714,8 @@ cleanup(struct bar *_bar) tll_foreach(backend->buffers, it) { if (it->item.wl_buf != NULL) wl_buffer_destroy(it->item.wl_buf); - if (it->item.cairo != NULL) - cairo_destroy(it->item.cairo); - if (it->item.cairo_surface != NULL) - cairo_surface_destroy(it->item.cairo_surface); + if (it->item.pix != NULL) + pixman_image_unref(it->item.pix); munmap(it->item.mmapped, it->item.size); tll_remove(backend->buffers, it); @@ -778,8 +762,7 @@ cleanup(struct bar *_bar) wl_display_disconnect(backend->display); /* Destroyed when freeing buffer list */ - bar->cairo_surface = NULL; - bar->cairo = NULL; + bar->pix = NULL; } @@ -901,31 +884,12 @@ frame_callback(void *data, struct wl_callback *wl_callback, uint32_t callback_da ;//printf("nothing more to do\n"); } -static pixman_image_t * -get_pixman_image(const struct bar *_bar) -{ - struct private *bar = _bar->private; - - cairo_surface_t *surf = cairo_get_target(bar->cairo); - cairo_surface_flush(surf); - - return pixman_image_create_bits_no_clear( - PIXMAN_a8r8g8b8, - cairo_image_surface_get_width(surf), - cairo_image_surface_get_height(surf), - (uint32_t *)cairo_image_surface_get_data(surf), - cairo_image_surface_get_stride(surf)); -} - static void -commit_pixman(const struct bar *_bar, pixman_image_t *pix) +commit(const struct bar *_bar) { struct private *bar = _bar->private; struct wayland_backend *backend = bar->backend.data; - pixman_image_unref(pix); - cairo_surface_mark_dirty(cairo_get_target(bar->cairo)); - //printf("commit: %dxl%d\n", backend->width, backend->height); assert(backend->next_buffer != NULL); @@ -958,9 +922,7 @@ commit_pixman(const struct bar *_bar, pixman_image_t *pix) backend->next_buffer = get_buffer(backend); assert(backend->next_buffer != NULL && backend->next_buffer->busy); - - bar->cairo_surface = backend->next_buffer->cairo_surface; - bar->cairo = backend->next_buffer->cairo; + bar->pix = backend->next_buffer->pix; } static void @@ -992,8 +954,7 @@ const struct backend wayland_backend_iface = { .setup = &setup, .cleanup = &cleanup, .loop = &loop, - .get_pixman_image = &get_pixman_image, - .commit_pixman = &commit_pixman, + .commit = &commit, .refresh = &refresh, .set_cursor = &set_cursor, }; diff --git a/bar/xcb.c b/bar/xcb.c index 3b71d27..e2209dd 100644 --- a/bar/xcb.c +++ b/bar/xcb.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -18,6 +19,7 @@ #define LOG_MODULE "bar:xcb" #include "../log.h" +#include "../stride.h" #include "../xcb.h" struct xcb_backend { @@ -27,10 +29,15 @@ struct xcb_backend { xcb_window_t win; xcb_colormap_t colormap; - xcb_pixmap_t pixmap; xcb_gc_t gc; xcb_cursor_context_t *cursor_ctx; xcb_cursor_t cursor; + + uint8_t depth; + void *client_pixmap; + size_t client_pixmap_size; + pixman_image_t *pix; + }; void * @@ -131,6 +138,7 @@ setup(struct bar *_bar) assert(depth == 32 || depth == 24); assert(vis != NULL); + backend->depth = depth; LOG_DBG("using a %hhu-bit visual", depth); backend->colormap = xcb_generate_id(backend->conn); @@ -234,19 +242,20 @@ setup(struct bar *_bar) _NET_WM_STRUT_PARTIAL, XCB_ATOM_CARDINAL, 32, 12, strut); - backend->pixmap = xcb_generate_id(backend->conn); - xcb_create_pixmap(backend->conn, depth, backend->pixmap, backend->win, - bar->width, bar->height_with_border); - backend->gc = xcb_generate_id(backend->conn); - xcb_create_gc(backend->conn, backend->gc, backend->pixmap, + xcb_create_gc(backend->conn, backend->gc, backend->win, XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES, (const uint32_t []){screen->white_pixel, 0}); - LOG_DBG("cairo: %s", cairo_version_string()); - bar->cairo_surface = cairo_xcb_surface_create( - backend->conn, backend->pixmap, vis, bar->width, bar->height_with_border); - bar->cairo = cairo_create(bar->cairo_surface); + const uint32_t stride = stride_for_format_and_width( + PIXMAN_a8r8g8b8, bar->width); + + backend->client_pixmap_size = stride * bar->height_with_border; + backend->client_pixmap = malloc(backend->client_pixmap_size); + backend->pix = pixman_image_create_bits_no_clear( + PIXMAN_a8r8g8b8, bar->width, bar->height_with_border, + (uint32_t *)backend->client_pixmap, stride); + bar->pix = backend->pix; xcb_map_window(backend->conn, backend->win); @@ -274,10 +283,12 @@ cleanup(struct bar *_bar) /* TODO: move to bar.c */ free(bar->cursor_name); + if (backend->pix != NULL) + pixman_image_unref(backend->pix); + free(backend->client_pixmap); + if (backend->gc != 0) xcb_free_gc(backend->conn, backend->gc); - if (backend->pixmap != 0) - xcb_free_pixmap(backend->conn, backend->pixmap); if (backend->win != 0) xcb_destroy_window(backend->conn, backend->win); if (backend->colormap != 0) @@ -370,58 +381,15 @@ loop(struct bar *_bar, } static void -free_pixman_bits(pixman_image_t *pix, void *data) -{ - free(data); -} - -static pixman_image_t * -get_pixman_image(const struct bar *_bar) -{ - const struct private *bar = _bar->private; - uint32_t *bits = malloc( - bar->width * bar->height_with_border * sizeof(uint32_t)); - - pixman_image_t *ret = pixman_image_create_bits_no_clear( - PIXMAN_a8r8g8b8, - bar->width, - bar->height_with_border, - bits, - bar->width * sizeof(uint32_t)); - - if (ret == NULL) { - free(bits); - return NULL; - } - - pixman_image_set_destroy_function(ret, &free_pixman_bits, bits); - return ret; -} - -static void -commit_pixman(const struct bar *_bar, pixman_image_t *pix) +commit(const struct bar *_bar) { const struct private *bar = _bar->private; const struct xcb_backend *backend = bar->backend.data; - /* Blit pixman image to our XCB surface */ - cairo_surface_t *surf = cairo_image_surface_create_for_data( - (unsigned char *)pixman_image_get_data(pix), - CAIRO_FORMAT_ARGB32, - bar->width, - bar->height_with_border, - cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, bar->width)); - - cairo_set_source_surface(bar->cairo, surf, 0, 0); - cairo_set_operator(bar->cairo, CAIRO_OPERATOR_SOURCE); - cairo_paint(bar->cairo); - - cairo_surface_flush(bar->cairo_surface); - cairo_surface_destroy(surf); - pixman_image_unref(pix); - - xcb_copy_area(backend->conn, backend->pixmap, backend->win, backend->gc, - 0, 0, 0, 0, bar->width, bar->height_with_border); + xcb_put_image( + backend->conn, XCB_IMAGE_FORMAT_Z_PIXMAP, backend->win, backend->gc, + bar->width, bar->height_with_border, 0, 0, 0, + backend->depth, backend->client_pixmap_size, backend->client_pixmap); xcb_flush(backend->conn); } @@ -476,8 +444,7 @@ const struct backend xcb_backend_iface = { .setup = &setup, .cleanup = &cleanup, .loop = &loop, - .get_pixman_image = &get_pixman_image, - .commit_pixman = &commit_pixman, + .commit = &commit, .refresh = &refresh, .set_cursor = &set_cursor, };