diff --git a/src/backend/backend.c b/src/backend/backend.c index 9eab5463..7295ecfc 100644 --- a/src/backend/backend.c +++ b/src/backend/backend.c @@ -10,13 +10,14 @@ #include "region.h" #include "win.h" -extern struct backend_operations xrender_ops; +extern struct backend_operations xrender_ops, dummy_ops; #ifdef CONFIG_OPENGL extern struct backend_operations glx_ops; #endif struct backend_operations *backend_list[NUM_BKEND] = { [BKEND_XRENDER] = &xrender_ops, + [BKEND_DUMMY] = &dummy_ops, #ifdef CONFIG_OPENGL [BKEND_GLX] = &glx_ops, #endif diff --git a/src/backend/backend.h b/src/backend/backend.h index fa01c800..65682914 100644 --- a/src/backend/backend.h +++ b/src/backend/backend.h @@ -225,8 +225,10 @@ struct backend_operations { // =========== Hooks ============ /// Let the backend hook into the event handling queue + /// Not implemented yet void (*set_ready_callback)(backend_t *, backend_ready_callback_t cb); /// Called right after compton has handled its events. + /// Not implemented yet void (*handle_events)(backend_t *); // =========== Misc ============ /// Return the driver that is been used by the backend diff --git a/src/backend/dummy/dummy.c b/src/backend/dummy/dummy.c new file mode 100644 index 00000000..17ad53e0 --- /dev/null +++ b/src/backend/dummy/dummy.c @@ -0,0 +1,159 @@ +#include +#include + +#include "backend/backend_common.h" +#include "common.h" +#include "compiler.h" +#include "uthash_extra.h" +#include "utils.h" + +struct dummy_image { + xcb_pixmap_t pixmap; + bool transparent; + int refcount; + UT_hash_handle hh; +}; + +struct dummy_data { + struct backend_base base; + struct dummy_image *images; +}; + +struct backend_base *dummy_init(struct session *ps attr_unused) { + return (struct backend_base *)ccalloc(1, struct dummy_data); +} + +void dummy_deinit(struct backend_base *data) { + auto dummy = (struct dummy_data *)data; + HASH_ITER2(dummy->images, img) { + log_warn("Backend image for pixmap %#010x is not freed", img->pixmap); + HASH_DEL(dummy->images, img); + free(img); + } + free(dummy); +} + +void dummy_compose(struct backend_base *base, void *image, int dst_x attr_unused, + int dst_y attr_unused, const region_t *reg_paint attr_unused, + const region_t *reg_visible attr_unused) { + auto dummy = (struct dummy_data *)base; + auto img = (struct dummy_image *)image; + + struct dummy_image *tmp = NULL; + HASH_FIND_INT(dummy->images, &img->pixmap, tmp); + if (!tmp) { + log_warn("Composing with an invalid (possibly freed) image"); + } +} + +void dummy_fill(struct backend_base *backend_data attr_unused, struct color c attr_unused, + const region_t *clip attr_unused) { +} + +bool dummy_blur(struct backend_base *backend_data attr_unused, double opacity attr_unused, + void *blur_ctx attr_unused, const region_t *reg_blur attr_unused, + const region_t *reg_visible attr_unused) { + return true; +} + +void *dummy_bind_pixmap(struct backend_base *base, xcb_pixmap_t pixmap, + struct xvisual_info fmt, bool owned attr_unused) { + auto dummy = (struct dummy_data *)base; + struct dummy_image *img = NULL; + HASH_FIND_INT(dummy->images, &pixmap, img); + if (img) { + img->refcount++; + return img; + } + + img = ccalloc(1, struct dummy_image); + img->pixmap = pixmap; + img->transparent = fmt.alpha_size != 0; + img->refcount = 1; + + HASH_ADD_INT(dummy->images, pixmap, img); + return (void *)img; +} + +void dummy_release_image(backend_t *base, void *image) { + auto dummy = (struct dummy_data *)base; + auto img = (struct dummy_image *)image; + assert(img->refcount > 0); + img->refcount--; + if (img->refcount == 0) { + HASH_DEL(dummy->images, img); + free(img); + } +} + +bool dummy_is_image_transparent(struct backend_base *base, void *image) { + auto dummy = (struct dummy_data *)base; + auto img = (struct dummy_image *)image; + struct dummy_image *tmp = NULL; + HASH_FIND_INT(dummy->images, &img->pixmap, tmp); + if (!tmp) { + log_warn("Using an invalid (possibly freed) image"); + } + return img->transparent; +} + +int dummy_buffer_age(struct backend_base *base attr_unused) { + return 2; +} + +bool dummy_image_op(struct backend_base *base attr_unused, enum image_operations op attr_unused, + void *image attr_unused, const region_t *reg_op attr_unused, + const region_t *reg_visible attr_unused, void *args attr_unused) { + return true; +} + +void *dummy_image_copy(struct backend_base *base, const void *image, + const region_t *reg_visible attr_unused) { + auto dummy = (struct dummy_data *)base; + auto img = (struct dummy_image *)image; + struct dummy_image *tmp = NULL; + HASH_FIND_INT(dummy->images, &img->pixmap, tmp); + if (!tmp) { + log_warn("Using an invalid (possibly freed) image"); + } + img->refcount++; + return img; +} + +void *dummy_create_blur_context(struct backend_base *base attr_unused, + enum blur_method method attr_unused, void *args attr_unused) { + static int dummy_context; + return &dummy_context; +} + +void dummy_destroy_blur_context(struct backend_base *base attr_unused, void *ctx attr_unused) { + +} + +void dummy_get_blur_size(void *ctx attr_unused, int *width, int *height) { + // These numbers are arbitrary, to make sure the reisze_region code path is + // covered. + *width = 5; + *height = 5; +} + +struct backend_operations dummy_ops = { + .init = dummy_init, + .deinit = dummy_deinit, + .compose = dummy_compose, + .fill = dummy_fill, + .blur = dummy_blur, + .bind_pixmap = dummy_bind_pixmap, + .render_shadow = default_backend_render_shadow, + .release_image = dummy_release_image, + .is_image_transparent = dummy_is_image_transparent, + .buffer_age = dummy_buffer_age, + .max_buffer_age = 5, + + .image_op = dummy_image_op, + .copy = dummy_image_copy, + .create_blur_context = dummy_create_blur_context, + .destroy_blur_context = dummy_destroy_blur_context, + .get_blur_size = dummy_get_blur_size, + +}; diff --git a/src/backend/meson.build b/src/backend/meson.build index 9318b78f..b8f0ad9a 100644 --- a/src/backend/meson.build +++ b/src/backend/meson.build @@ -1,5 +1,5 @@ # enable xrender -srcs += [ files('backend_common.c', 'xrender/xrender.c', 'backend.c', 'driver.c') ] +srcs += [ files('backend_common.c', 'xrender/xrender.c', 'dummy/dummy.c', 'backend.c', 'driver.c') ] # enable opengl if get_option('opengl') diff --git a/src/compton.c b/src/compton.c index 2e32eb6a..63d951eb 100644 --- a/src/compton.c +++ b/src/compton.c @@ -80,10 +80,11 @@ const char *const WINTYPES[NUM_WINTYPES] = { }; /// Names of backends. -const char *const BACKEND_STRS[NUM_BKEND + 1] = {"xrender", // BKEND_XRENDER - "glx", // BKEND_GLX - "xr_glx_hybrid", // BKEND_XR_GLX_HYBRID - NULL}; +const char *const BACKEND_STRS[] = {[BKEND_XRENDER] = "xrender", + [BKEND_GLX] = "glx", + [BKEND_XR_GLX_HYBRID] = "xr_glx_hybrid", + [BKEND_DUMMY] = "dummy", + NULL}; // === Global variables === diff --git a/src/config.h b/src/config.h index f8e1dd05..6507e189 100644 --- a/src/config.h +++ b/src/config.h @@ -34,6 +34,7 @@ enum backend { BKEND_XRENDER, BKEND_GLX, BKEND_XR_GLX_HYBRID, + BKEND_DUMMY, NUM_BKEND, }; diff --git a/src/render.c b/src/render.c index 43a11643..6ac22fdd 100644 --- a/src/render.c +++ b/src/render.c @@ -1087,6 +1087,10 @@ static bool init_alpha_picts(session_t *ps) { } bool init_render(session_t *ps) { + if (ps->o.backend == BKEND_DUMMY) { + return false; + } + // Initialize OpenGL as early as possible #ifdef CONFIG_OPENGL glxext_init(ps->dpy, ps->scr);