From 2d98518b7d5ce3a6a688aa434447cba800f57b87 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Sat, 10 Feb 2024 08:20:10 +0000 Subject: [PATCH] backend: give images a type It's quite confusing what should be passed into what because too many things are `void *`. So give images a type to make things a bit clearer. Because of C's limited type system, we lose the ability to annotate them as nonnull or const, well you win some you lose some. Also while doing this I noticed error handling around this is a bit lacking. Co-authored-by: Maxim Solovyov Signed-off-by: Yuxuan Shui --- src/backend/backend.h | 87 ++++++++++++++++++++++------------- src/backend/backend_common.c | 28 +++++------ src/backend/backend_common.h | 12 ++--- src/backend/dummy/dummy.c | 54 +++++++++++----------- src/backend/gl/blur.c | 15 +++--- src/backend/gl/egl.c | 4 +- src/backend/gl/gl_common.c | 37 +++++++-------- src/backend/gl/gl_common.h | 31 +++++++------ src/backend/gl/glx.c | 4 +- src/backend/xrender/xrender.c | 43 +++++++++-------- src/common.h | 2 +- src/win.h | 6 +-- 12 files changed, 177 insertions(+), 146 deletions(-) diff --git a/src/backend/backend.h b/src/backend/backend.h index fba17bbd..556803c1 100644 --- a/src/backend/backend.h +++ b/src/backend/backend.h @@ -115,6 +115,10 @@ struct dual_kawase_blur_args { int strength; }; +typedef struct { + // Intentionally left blank +} *image_handle; + struct backend_operations { // =========== Initialization =========== @@ -167,26 +171,27 @@ struct backend_operations { * Paint the content of an image onto the rendering buffer. * * @param backend_data the backend data - * @param image_data the image to paint + * @param image the image to paint, cannot be NULL * @param dst_x, dst_y the top left corner of the image in the target * @param mask the mask image, the top left of the mask is aligned with - * the top left of the image + * the top left of the image. Optional, can be + * NULL. * @param reg_paint the clip region, in target coordinates * @param reg_visible the visible region, in target coordinates */ - void (*compose)(backend_t *backend_data, void *image_data, coord_t image_dst, - void *mask, coord_t mask_dst, const region_t *reg_paint, - const region_t *reg_visible); + void (*compose)(backend_t *backend_data, image_handle image, coord_t image_dst, + image_handle mask, coord_t mask_dst, const region_t *reg_paint, + const region_t *reg_visible) attr_nonnull(1, 2, 6, 7); /// Fill rectangle of the rendering buffer, mostly for debug purposes, optional. void (*fill)(backend_t *backend_data, struct color, const region_t *clip); /// Blur a given region of the rendering buffer. /// - /// The blur is limited by `mask`. `mask_dst` specifies the top left corner of the - /// mask is. - bool (*blur)(backend_t *backend_data, double opacity, void *blur_ctx, void *mask, - coord_t mask_dst, const region_t *reg_blur, + /// The blur can be limited by `mask`. `mask_dst` specifies the top left corner of + /// the mask. `mask` can be NULL. + bool (*blur)(backend_t *backend_data, double opacity, void *blur_ctx, + image_handle mask, coord_t mask_dst, const region_t *reg_blur, const region_t *reg_visible) attr_nonnull(1, 3, 6, 7); /// Update part of the back buffer with the rendering buffer, then present the @@ -202,13 +207,15 @@ struct backend_operations { * Bind a X pixmap to the backend's internal image data structure. * * @param backend_data backend data - * @param pixmap X pixmap to bind - * @param fmt information of the pixmap's visual - * @param owned whether the ownership of the pixmap is transferred to the backend - * @return backend internal data structure bound with this pixmap + * @param pixmap X pixmap to bind + * @param fmt information of the pixmap's visual + * @param owned whether the ownership of the pixmap is transferred to the + * backend. + * @return backend specific image handle for the pixmap. May be + * NULL. */ - void *(*bind_pixmap)(backend_t *backend_data, xcb_pixmap_t pixmap, - struct xvisual_info fmt, bool owned); + image_handle (*bind_pixmap)(backend_t *backend_data, xcb_pixmap_t pixmap, + struct xvisual_info fmt, bool owned); /// Create a shadow context for rendering shadows with radius `radius`. /// Default implementation: default_create_shadow_context @@ -224,17 +231,23 @@ struct backend_operations { /// shadow context is created. /// Default implementation: default_render_shadow /// + /// @return the shadow image, may be NULL. + /// /// Required. - void *(*render_shadow)(backend_t *backend_data, int width, int height, - struct backend_shadow_context *ctx, struct color color); + image_handle (*render_shadow)(backend_t *backend_data, int width, int height, + struct backend_shadow_context *ctx, struct color color); /// Create a shadow by blurring a mask. `size` is the size of the blur. The /// backend can use whichever blur method is the fastest. The shadow produced /// shoule be consistent with `render_shadow`. /// + /// @param mask the input mask, must not be NULL. + /// @return the shadow image, may be NULL. + /// /// Optional. - void *(*shadow_from_mask)(backend_t *backend_data, void *mask, - struct backend_shadow_context *ctx, struct color color); + image_handle (*shadow_from_mask)(backend_t *backend_data, image_handle mask, + struct backend_shadow_context *ctx, + struct color color); /// Create a mask image from region `reg`. This region can be used to create /// shadow, or used as a mask for composing. When used as a mask, it should mask @@ -245,13 +258,18 @@ struct backend_operations { /// and outside of the mask. Corner radius should exclude the corners from the /// mask. Corner radius should be applied before the inversion. /// + /// @return the mask image, may be NULL. + /// /// Required. - void *(*make_mask)(backend_t *backend_data, geometry_t size, const region_t *reg); + image_handle (*make_mask)(backend_t *backend_data, geometry_t size, + const region_t *reg); // ============ Resource management =========== /// Free resources associated with an image data structure - void (*release_image)(backend_t *backend_data, void *img_data) attr_nonnull(1, 2); + /// + /// @param image the image to be released, cannot be NULL. + void (*release_image)(backend_t *backend_data, image_handle image) attr_nonnull(1, 2); /// Create a shader object from a shader source. /// @@ -276,7 +294,9 @@ struct backend_operations { /// This function is needed because some backend might change the content of the /// window (e.g. when using a custom shader with the glx backend), so only the /// backend knows if an image is transparent. - bool (*is_image_transparent)(backend_t *backend_data, void *image_data) + /// + /// @param image the image to be checked, must not be NULL. + bool (*is_image_transparent)(backend_t *backend_data, image_handle image) attr_nonnull(1, 2); /// Get the age of the buffer content we are currently rendering on top @@ -311,36 +331,39 @@ struct backend_operations { * * @param backend_data backend data * @param prop the property to change - * @param image_data an image data structure returned by the backend + * @param image an image handle, cannot be NULL. * @param args property value - * @return whether the operation is successful + * @return whether the operation is successful */ bool (*set_image_property)(backend_t *backend_data, enum image_properties prop, - void *image_data, void *args); + image_handle image, void *args) attr_nonnull(1, 3); /** * Manipulate an image. Image properties are untouched. * * @param backend_data backend data * @param op the operation to perform - * @param image_data an image data structure returned by the backend + * @param image an image handle, cannot be NULL. * @param reg_op the clip region, define the part of the image to be * operated on. * @param reg_visible define the part of the image that will eventually * be visible on target. this is a hint to the backend * for optimization purposes. * @param args extra arguments, operation specific - * @return whether the operation is successful + * @return whether the operation is successful */ - bool (*image_op)(backend_t *backend_data, enum image_operations op, void *image_data, - const region_t *reg_op, const region_t *reg_visible, void *args); + bool (*image_op)(backend_t *backend_data, enum image_operations op, + image_handle image, const region_t *reg_op, + const region_t *reg_visible, void *args) attr_nonnull(1, 3, 4, 5); - /// Create another instance of the `image_data`. The newly created image + /// Create another instance of the `image`. The newly created image /// inherits its content and all image properties from the image being /// cloned. All `image_op` and `set_image_property` calls on the /// returned image should not affect the original image. - void *(*clone_image)(backend_t *base, const void *image_data, - const region_t *reg_visible); + /// + /// @param image the image to be cloned, must not be NULL. + image_handle (*clone_image)(backend_t *base, image_handle image, + const region_t *reg_visible) attr_nonnull_all; /// Create a blur context that can be used to call `blur` void *(*create_blur_context)(backend_t *base, enum blur_method, void *args); diff --git a/src/backend/backend_common.c b/src/backend/backend_common.c index eef21459..5a1b785e 100644 --- a/src/backend/backend_common.c +++ b/src/backend/backend_common.c @@ -293,8 +293,8 @@ shadow_picture_err: return false; } -void *default_render_shadow(backend_t *backend_data, int width, int height, - struct backend_shadow_context *sctx, struct color color) { +image_handle default_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, true, 1, color.red, color.green, color.blue); @@ -308,7 +308,7 @@ void *default_render_shadow(backend_t *backend_data, int width, int height, } auto visual = x_get_visual_for_standard(backend_data->c, XCB_PICT_STANDARD_ARGB_32); - void *ret = backend_data->ops->bind_pixmap( + auto ret = backend_data->ops->bind_pixmap( backend_data, shadow, x_get_visual_info(backend_data->c, visual), true); x_free_picture(backend_data->c, pict); x_free_picture(backend_data->c, shadow_pixel); @@ -316,16 +316,16 @@ void *default_render_shadow(backend_t *backend_data, int width, int height, } /// Implement render_shadow with shadow_from_mask -void * +image_handle backend_render_shadow_from_mask(backend_t *backend_data, int width, int height, struct backend_shadow_context *sctx, struct color color) { region_t reg; pixman_region32_init_rect(®, 0, 0, (unsigned int)width, (unsigned int)height); - void *mask = backend_data->ops->make_mask( + auto mask = backend_data->ops->make_mask( backend_data, (geometry_t){.width = width, .height = height}, ®); pixman_region32_fini(®); - void *shadow = backend_data->ops->shadow_from_mask(backend_data, mask, sctx, color); + auto shadow = backend_data->ops->shadow_from_mask(backend_data, mask, sctx, color); backend_data->ops->release_image(backend_data, mask); return shadow; } @@ -458,17 +458,17 @@ struct dual_kawase_params *generate_dual_kawase_params(void *args) { return params; } -void *default_clone_image(backend_t *base attr_unused, const void *image_data, - const region_t *reg_visible attr_unused) { +image_handle default_clone_image(backend_t *base attr_unused, image_handle image, + const region_t *reg_visible attr_unused) { auto new_img = ccalloc(1, struct backend_image); - *new_img = *(struct backend_image *)image_data; + *new_img = *(struct backend_image *)image; new_img->inner->refcount++; - return new_img; + return (image_handle)new_img; } bool default_set_image_property(backend_t *base attr_unused, enum image_properties op, - void *image_data, void *arg) { - struct backend_image *tex = image_data; + image_handle image, void *arg) { + auto tex = (struct backend_image *)image; int *iargs = arg; bool *bargs = arg; double *dargs = arg; @@ -490,8 +490,8 @@ bool default_set_image_property(backend_t *base attr_unused, enum image_properti return true; } -bool default_is_image_transparent(backend_t *base attr_unused, void *image_data) { - struct backend_image *img = image_data; +bool default_is_image_transparent(backend_t *base attr_unused, image_handle image) { + auto img = (struct backend_image *)image; return img->opacity < 1 || img->inner->has_alpha; } diff --git a/src/backend/backend_common.h b/src/backend/backend_common.h index da9ccd02..20357c09 100644 --- a/src/backend/backend_common.h +++ b/src/backend/backend_common.h @@ -54,11 +54,11 @@ solid_picture(struct x_connection *, bool argb, double a, double r, double g, do xcb_image_t *make_shadow(struct x_connection *c, const conv *kernel, double opacity, int width, int height); -void *default_render_shadow(backend_t *backend_data, int width, int height, - struct backend_shadow_context *sctx, struct color color); +image_handle default_render_shadow(backend_t *backend_data, int width, int height, + struct backend_shadow_context *sctx, struct color color); /// Implement `render_shadow` with `shadow_from_mask`. -void * +image_handle backend_render_shadow_from_mask(backend_t *backend_data, int width, int height, struct backend_shadow_context *sctx, struct color color); struct backend_shadow_context * @@ -72,8 +72,8 @@ void init_backend_base(struct backend_base *base, session_t *ps); struct conv **generate_blur_kernel(enum blur_method method, void *args, int *kernel_count); struct dual_kawase_params *generate_dual_kawase_params(void *args); -void *default_clone_image(backend_t *base, const void *image_data, const region_t *reg); -bool default_is_image_transparent(backend_t *base attr_unused, void *image_data); +image_handle default_clone_image(backend_t *base, image_handle image, const region_t *reg); +bool default_is_image_transparent(backend_t *base attr_unused, image_handle image); bool default_set_image_property(backend_t *base attr_unused, enum image_properties op, - void *image_data, void *arg); + image_handle image, void *arg); struct backend_image *default_new_backend_image(int w, int h); diff --git a/src/backend/dummy/dummy.c b/src/backend/dummy/dummy.c index 3e57c039..bab7c931 100644 --- a/src/backend/dummy/dummy.c +++ b/src/backend/dummy/dummy.c @@ -50,8 +50,9 @@ void dummy_deinit(struct backend_base *data) { free(dummy); } -static void dummy_check_image(struct backend_base *base, const struct dummy_image *img) { +static void dummy_check_image(struct backend_base *base, image_handle image) { auto dummy = (struct dummy_data *)base; + auto img = (struct dummy_image *)image; if (img == (struct dummy_image *)&dummy->mask) { return; } @@ -64,13 +65,13 @@ static void dummy_check_image(struct backend_base *base, const struct dummy_imag assert(*tmp->refcount > 0); } -void dummy_compose(struct backend_base *base, void *image, coord_t dst attr_unused, - void *mask attr_unused, coord_t mask_dst attr_unused, +void dummy_compose(struct backend_base *base, image_handle image, coord_t dst attr_unused, + image_handle mask attr_unused, coord_t mask_dst attr_unused, const region_t *reg_paint attr_unused, const region_t *reg_visible attr_unused) { auto dummy attr_unused = (struct dummy_data *)base; dummy_check_image(base, image); - assert(mask == NULL || mask == &dummy->mask); + assert(mask == NULL || (struct backend_image *)mask == &dummy->mask); } void dummy_fill(struct backend_base *backend_data attr_unused, struct color c attr_unused, @@ -78,20 +79,20 @@ void dummy_fill(struct backend_base *backend_data attr_unused, struct color c at } bool dummy_blur(struct backend_base *backend_data attr_unused, double opacity attr_unused, - void *blur_ctx attr_unused, void *mask attr_unused, + void *blur_ctx attr_unused, image_handle mask attr_unused, coord_t mask_dst 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) { +image_handle dummy_bind_pixmap(struct backend_base *base, xcb_pixmap_t pixmap, + struct xvisual_info fmt, bool owned) { auto dummy = (struct dummy_data *)base; struct dummy_image *img = NULL; HASH_FIND_INT(dummy->images, &pixmap, img); if (img) { (*img->refcount)++; - return img; + return (image_handle)img; } img = ccalloc(1, struct dummy_image); @@ -102,12 +103,12 @@ void *dummy_bind_pixmap(struct backend_base *base, xcb_pixmap_t pixmap, img->owned = owned; HASH_ADD_INT(dummy->images, pixmap, img); - return (void *)img; + return (image_handle)img; } -void dummy_release_image(backend_t *base, void *image) { +void dummy_release_image(backend_t *base, image_handle image) { auto dummy = (struct dummy_data *)base; - if (image == &dummy->mask) { + if ((struct backend_image *)image == &dummy->mask) { return; } auto img = (struct dummy_image *)image; @@ -123,10 +124,9 @@ void dummy_release_image(backend_t *base, void *image) { } } -bool dummy_is_image_transparent(struct backend_base *base, void *image) { - auto img = (struct dummy_image *)image; - dummy_check_image(base, img); - return img->transparent; +bool dummy_is_image_transparent(struct backend_base *base, image_handle image) { + dummy_check_image(base, image); + return ((struct dummy_image *)image)->transparent; } int dummy_buffer_age(struct backend_base *base attr_unused) { @@ -134,29 +134,31 @@ int dummy_buffer_age(struct backend_base *base attr_unused) { } bool dummy_image_op(struct backend_base *base, enum image_operations op attr_unused, - void *image, const region_t *reg_op attr_unused, + image_handle image, const region_t *reg_op attr_unused, const region_t *reg_visible attr_unused, void *args attr_unused) { dummy_check_image(base, image); return true; } -void *dummy_make_mask(struct backend_base *base, geometry_t size attr_unused, - const region_t *reg attr_unused) { - return &(((struct dummy_data *)base)->mask); +image_handle dummy_make_mask(struct backend_base *base, geometry_t size attr_unused, + const region_t *reg attr_unused) { + auto dummy = (struct dummy_data *)base; + auto mask = &dummy->mask; + return (image_handle)mask; } bool dummy_set_image_property(struct backend_base *base, enum image_properties prop attr_unused, - void *image, void *arg attr_unused) { + image_handle image, void *arg attr_unused) { dummy_check_image(base, image); return true; } -void *dummy_clone_image(struct backend_base *base, const void *image, - const region_t *reg_visible attr_unused) { - auto img = (const struct dummy_image *)image; - dummy_check_image(base, img); - (*img->refcount)++; - return (void *)img; +image_handle dummy_clone_image(struct backend_base *base, image_handle image, + const region_t *reg_visible attr_unused) { + dummy_check_image(base, image); + auto image_impl = (struct dummy_image *)image; + (*image_impl->refcount)++; + return image; } void *dummy_create_blur_context(struct backend_base *base attr_unused, diff --git a/src/backend/gl/blur.c b/src/backend/gl/blur.c index 328756fc..acdea761 100644 --- a/src/backend/gl/blur.c +++ b/src/backend/gl/blur.c @@ -256,10 +256,11 @@ bool gl_dual_kawase_blur(double opacity, struct gl_blur_context *bctx, const rec return true; } -bool gl_blur_impl(double opacity, struct gl_blur_context *bctx, void *mask, coord_t mask_dst, - const region_t *reg_blur, const region_t *reg_visible attr_unused, - GLuint source_texture, geometry_t source_size, GLuint target_fbo, - GLuint default_mask, bool high_precision) { +bool gl_blur_impl(double opacity, struct gl_blur_context *bctx, + struct backend_image *mask, coord_t mask_dst, const region_t *reg_blur, + const region_t *reg_visible attr_unused, GLuint source_texture, + geometry_t source_size, GLuint target_fbo, GLuint default_mask, + bool high_precision) { bool ret = false; if (source_size.width != bctx->fb_width || source_size.height != bctx->fb_height) { @@ -400,12 +401,12 @@ bool gl_blur_impl(double opacity, struct gl_blur_context *bctx, void *mask, coor return ret; } -bool gl_blur(backend_t *base, double opacity, void *ctx, void *mask, coord_t mask_dst, +bool gl_blur(backend_t *base, double opacity, void *ctx, image_handle mask, coord_t mask_dst, const region_t *reg_blur, const region_t *reg_visible attr_unused) { auto gd = (struct gl_data *)base; auto bctx = (struct gl_blur_context *)ctx; - return gl_blur_impl(opacity, bctx, mask, mask_dst, reg_blur, reg_visible, - gd->back_texture, + return gl_blur_impl(opacity, bctx, (struct backend_image *)mask, mask_dst, + reg_blur, reg_visible, gd->back_texture, (geometry_t){.width = gd->width, .height = gd->height}, gd->back_fbo, gd->default_mask_texture, gd->dithered_present); } diff --git a/src/backend/gl/egl.c b/src/backend/gl/egl.c index 9f3f153f..082a15d1 100644 --- a/src/backend/gl/egl.c +++ b/src/backend/gl/egl.c @@ -249,7 +249,7 @@ end: return &gd->gl.base; } -static void * +static image_handle egl_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, bool owned) { struct egl_data *gd = (void *)base; struct egl_pixmap *eglpixmap = NULL; @@ -301,7 +301,7 @@ egl_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, b glBindTexture(GL_TEXTURE_2D, 0); gl_check_err(); - return wd; + return (image_handle)wd; err: if (eglpixmap && eglpixmap->image) { eglDestroyImage(gd->display, eglpixmap->image); diff --git a/src/backend/gl/gl_common.c b/src/backend/gl/gl_common.c index 2ef41702..7480c78e 100644 --- a/src/backend/gl/gl_common.c +++ b/src/backend/gl/gl_common.c @@ -551,11 +551,12 @@ void x_rect_to_coords(int nrects, const rect_t *rects, coord_t image_dst, } // TODO(yshui) make use of reg_visible -void gl_compose(backend_t *base, void *image_data, coord_t image_dst, void *mask, - coord_t mask_dst, const region_t *reg_tgt, +void gl_compose(backend_t *base, image_handle image, coord_t image_dst, + image_handle mask_, coord_t mask_dst, const region_t *reg_tgt, const region_t *reg_visible attr_unused) { auto gd = (struct gl_data *)base; - struct backend_image *img = image_data; + auto img = (struct backend_image *)image; + auto mask = (struct backend_image *)mask_; auto inner = (struct gl_texture *)img->inner; // Painting @@ -709,7 +710,7 @@ void gl_fill(backend_t *base, struct color c, const region_t *clip) { return _gl_fill(base, c, clip, gd->back_fbo, gd->height, true); } -void *gl_make_mask(backend_t *base, geometry_t size, const region_t *reg) { +image_handle gl_make_mask(backend_t *base, geometry_t size, const region_t *reg) { auto tex = ccalloc(1, struct gl_texture); auto img = default_new_backend_image(size.width, size.height); tex->width = size.width; @@ -740,7 +741,7 @@ void *gl_make_mask(backend_t *base, geometry_t size, const region_t *reg) { glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glDeleteFramebuffers(1, &fbo); - return img; + return (image_handle)img; } static void gl_release_image_inner(backend_t *base, struct gl_texture *inner) { @@ -756,8 +757,8 @@ static void gl_release_image_inner(backend_t *base, struct gl_texture *inner) { gl_check_err(); } -void gl_release_image(backend_t *base, void *image_data) { - struct backend_image *wd = image_data; +void gl_release_image(backend_t *base, image_handle image) { + auto wd = (struct backend_image *)image; auto inner = (struct gl_texture *)wd->inner; inner->refcount--; assert(inner->refcount >= 0); @@ -1221,9 +1222,9 @@ bool gl_last_render_time(backend_t *base, struct timespec *ts) { return true; } -bool gl_image_op(backend_t *base, enum image_operations op, void *image_data, +bool gl_image_op(backend_t *base, enum image_operations op, image_handle image, const region_t *reg_op, const region_t *reg_visible attr_unused, void *arg) { - struct backend_image *tex = image_data; + auto tex = (struct backend_image *)image; switch (op) { case IMAGE_OP_APPLY_ALPHA: gl_image_decouple(base, tex); @@ -1236,12 +1237,12 @@ bool gl_image_op(backend_t *base, enum image_operations op, void *image_data, } bool gl_set_image_property(backend_t *backend_data, enum image_properties prop, - void *image_data, void *args) { + image_handle image, void *args) { if (prop != IMAGE_PROPERTY_CUSTOM_SHADER) { - return default_set_image_property(backend_data, prop, image_data, args); + return default_set_image_property(backend_data, prop, image, args); } - struct backend_image *img = image_data; + auto img = (struct backend_image *)image; auto inner = (struct gl_texture *)img->inner; inner->shader = args; return true; @@ -1280,12 +1281,12 @@ void gl_destroy_shadow_context(backend_t *base attr_unused, struct backend_shado free(ctx_); } -void *gl_shadow_from_mask(backend_t *base, void *mask, - struct backend_shadow_context *sctx, struct color color) { +image_handle gl_shadow_from_mask(backend_t *base, image_handle mask_, + struct backend_shadow_context *sctx, struct color color) { log_debug("Create shadow from mask"); auto gd = (struct gl_data *)base; - auto img = (struct backend_image *)mask; - auto inner = (struct gl_texture *)img->inner; + auto mask = (struct backend_image *)mask_; + auto inner = (struct gl_texture *)mask->inner; auto gsctx = (struct gl_shadow_context *)sctx; int radius = (int)gsctx->radius; @@ -1315,7 +1316,7 @@ void *gl_shadow_from_mask(backend_t *base, void *mask, glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, source_texture, 0); glDrawBuffer(GL_COLOR_ATTACHMENT0); - if (img->color_inverted) { + if (mask->color_inverted) { // If the mask is inverted, clear the source_texture to white, so the // "outside" of the mask would be correct glClearColor(1, 1, 1, 1); @@ -1424,7 +1425,7 @@ void *gl_shadow_from_mask(backend_t *base, void *mask, glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glDeleteFramebuffers(1, &fbo); gl_check_err(); - return new_img; + return (image_handle)new_img; } enum device_status gl_device_status(backend_t *base) { diff --git a/src/backend/gl/gl_common.h b/src/backend/gl/gl_common.h index 50bec7c6..cd2310cb 100644 --- a/src/backend/gl/gl_common.h +++ b/src/backend/gl/gl_common.h @@ -6,6 +6,7 @@ #include #include "backend/backend.h" +#include "backend/backend_common.h" #include "log.h" #include "region.h" @@ -143,13 +144,13 @@ void *gl_create_window_shader(backend_t *backend_data, const char *source); void gl_destroy_window_shader(backend_t *backend_data, void *shader); uint64_t gl_get_shader_attributes(backend_t *backend_data, void *shader); bool gl_set_image_property(backend_t *backend_data, enum image_properties prop, - void *image_data, void *args); + image_handle image, void *args); bool gl_last_render_time(backend_t *backend_data, struct timespec *time); /** * @brief Render a region with texture data. */ -void gl_compose(backend_t *, void *image_data, coord_t image_dst, void *mask, +void gl_compose(backend_t *, image_handle image, coord_t image_dst, image_handle mask, coord_t mask_dst, const region_t *reg_tgt, const region_t *reg_visible); void gl_resize(struct gl_data *, int width, int height); @@ -159,32 +160,32 @@ void gl_deinit(struct gl_data *gd); GLuint gl_new_texture(GLenum target); -bool gl_image_op(backend_t *base, enum image_operations op, void *image_data, +bool gl_image_op(backend_t *base, enum image_operations op, image_handle image, const region_t *reg_op, const region_t *reg_visible, void *arg); -void gl_release_image(backend_t *base, void *image_data); -void *gl_make_mask(backend_t *base, geometry_t size, const region_t *reg); +void gl_release_image(backend_t *base, image_handle image); +image_handle gl_make_mask(backend_t *base, geometry_t size, const region_t *reg); -void *gl_clone(backend_t *base, const void *image_data, const region_t *reg_visible); +image_handle gl_clone(backend_t *base, image_handle image, const region_t *reg_visible); -bool gl_blur(backend_t *base, double opacity, void *ctx, void *mask, coord_t mask_dst, - const region_t *reg_blur, const region_t *reg_visible); -bool gl_blur_impl(double opacity, struct gl_blur_context *bctx, void *mask, coord_t mask_dst, - const region_t *reg_blur, const region_t *reg_visible attr_unused, - GLuint source_texture, geometry_t source_size, GLuint target_fbo, - GLuint default_mask, bool high_precision); +bool gl_blur(backend_t *base, double opacity, void *ctx, image_handle mask, + coord_t mask_dst, const region_t *reg_blur, const region_t *reg_visible); +bool gl_blur_impl(double opacity, struct gl_blur_context *bctx, + struct backend_image *mask, coord_t mask_dst, const region_t *reg_blur, + const region_t *reg_visible attr_unused, GLuint source_texture, + geometry_t source_size, GLuint target_fbo, GLuint default_mask, + bool high_precision); void *gl_create_blur_context(backend_t *base, enum blur_method, void *args); void gl_destroy_blur_context(backend_t *base, void *ctx); struct backend_shadow_context *gl_create_shadow_context(backend_t *base, double radius); void gl_destroy_shadow_context(backend_t *base attr_unused, struct backend_shadow_context *ctx); -void *gl_shadow_from_mask(backend_t *base, void *mask, - struct backend_shadow_context *sctx, struct color color); +image_handle gl_shadow_from_mask(backend_t *base, image_handle mask, + struct backend_shadow_context *sctx, struct color color); void gl_get_blur_size(void *blur_context, int *width, int *height); void gl_fill(backend_t *base, struct color, const region_t *clip); void gl_present(backend_t *base, const region_t *); -bool gl_read_pixel(backend_t *base, void *image_data, int x, int y, struct color *output); enum device_status gl_device_status(backend_t *base); /** diff --git a/src/backend/gl/glx.c b/src/backend/gl/glx.c index 1047af91..a985e3fc 100644 --- a/src/backend/gl/glx.c +++ b/src/backend/gl/glx.c @@ -380,7 +380,7 @@ end: return &gd->gl.base; } -static void * +static image_handle glx_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, bool owned) { struct _glx_pixmap *glxpixmap = NULL; auto gd = (struct _glx_data *)base; @@ -475,7 +475,7 @@ glx_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, b glBindTexture(GL_TEXTURE_2D, 0); gl_check_err(); - return wd; + return (image_handle)wd; err: if (glxpixmap && glxpixmap->glpixmap) { glXDestroyPixmap(base->c->dpy, glxpixmap->glpixmap); diff --git a/src/backend/xrender/xrender.c b/src/backend/xrender/xrender.c index acfe25d4..72d5ece6 100644 --- a/src/backend/xrender/xrender.c +++ b/src/backend/xrender/xrender.c @@ -359,10 +359,12 @@ compose_impl(struct _xrender_data *xd, struct xrender_image *xrimg, coord_t dst, pixman_region32_fini(®); } -static void compose(backend_t *base, void *img_data, coord_t dst, void *mask, coord_t mask_dst, - const region_t *reg_paint, const region_t *reg_visible) { +static void compose(backend_t *base, image_handle image_, coord_t dst, image_handle mask_, + coord_t mask_dst, const region_t *reg_paint, const region_t *reg_visible) { struct _xrender_data *xd = (void *)base; - return compose_impl(xd, img_data, dst, mask, mask_dst, reg_paint, reg_visible, + auto image = (struct xrender_image *)image_; + auto mask = (struct xrender_image *)mask_; + return compose_impl(xd, image, dst, mask, mask_dst, reg_paint, reg_visible, xd->back[2]); } @@ -384,9 +386,10 @@ static void fill(backend_t *base, struct color c, const region_t *clip) { .height = to_u16_checked(extent->y2 - extent->y1)}}); } -static bool blur(backend_t *backend_data, double opacity, void *ctx_, void *mask, +static bool blur(backend_t *backend_data, double opacity, void *ctx_, image_handle mask_, coord_t mask_dst, const region_t *reg_blur, const region_t *reg_visible) { - struct _xrender_blur_context *bctx = ctx_; + auto bctx = (struct _xrender_blur_context *)ctx_; + auto mask = (struct xrender_image *)mask_; if (bctx->method == BLUR_METHOD_NONE) { return true; } @@ -517,7 +520,7 @@ static bool blur(backend_t *backend_data, double opacity, void *ctx_, void *mask return true; } -static void * +static image_handle bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, bool owned) { xcb_generic_error_t *e; auto r = xcb_get_geometry_reply(base->c->c, xcb_get_geometry(base->c->c, pixmap), &e); @@ -552,7 +555,7 @@ bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, bool free(img); return NULL; } - return img; + return (image_handle)img; } static void release_image_inner(backend_t *base, struct _xrender_image_data_inner *inner) { x_free_picture(base->c, inner->pict); @@ -576,13 +579,13 @@ release_rounded_corner_cache(backend_t *base, struct xrender_rounded_rectangle_c } } -static void release_image(backend_t *base, void *image) { - struct xrender_image *img = image; +static void release_image(backend_t *base, image_handle image) { + auto img = (struct xrender_image *)image; release_rounded_corner_cache(base, img->rounded_rectangle); img->rounded_rectangle = NULL; img->base.inner->refcount -= 1; if (img->base.inner->refcount == 0) { - release_image_inner(base, (void *)img->base.inner); + release_image_inner(base, (struct _xrender_image_data_inner *)img->base.inner); } free(img); } @@ -711,7 +714,7 @@ new_inner(backend_t *base, int w, int h, xcb_visualid_t visual, uint8_t depth) { return new_inner; } -static void *make_mask(backend_t *base, geometry_t size, const region_t *reg) { +static image_handle make_mask(backend_t *base, geometry_t size, const region_t *reg) { struct _xrender_data *xd = (void *)base; // Give the mask a 1 pixel wide border to emulate the clamp to border behavior of // OpenGL textures. @@ -754,7 +757,7 @@ static void *make_mask(backend_t *base, geometry_t size, const region_t *reg) { img->base.dim = 0; img->base.inner = (struct backend_image_inner_base *)inner; img->rounded_rectangle = NULL; - return img; + return (image_handle)img; } static bool decouple_image(backend_t *base, struct backend_image *img, const region_t *reg) { @@ -782,10 +785,10 @@ static bool decouple_image(backend_t *base, struct backend_image *img, const reg return true; } -static bool image_op(backend_t *base, enum image_operations op, void *image, +static bool image_op(backend_t *base, enum image_operations op, image_handle image, const region_t *reg_op, const region_t *reg_visible, void *arg) { struct _xrender_data *xd = (void *)base; - struct backend_image *img = image; + auto img = (struct backend_image *)image; region_t reg; double *dargs = arg; @@ -964,19 +967,19 @@ err: return NULL; } -void *clone_image(backend_t *base attr_unused, const void *image_data, - const region_t *reg_visible attr_unused) { +image_handle clone_image(backend_t *base attr_unused, image_handle image, + const region_t *reg_visible attr_unused) { auto new_img = ccalloc(1, struct xrender_image); - *new_img = *(struct xrender_image *)image_data; + *new_img = *(struct xrender_image *)image; new_img->base.inner->refcount++; if (new_img->rounded_rectangle) { new_img->rounded_rectangle->refcount++; } - return new_img; + return (image_handle)new_img; } -static bool -set_image_property(backend_t *base, enum image_properties op, void *image, void *args) { +static bool set_image_property(backend_t *base, enum image_properties op, + image_handle image, void *args) { auto xrimg = (struct xrender_image *)image; if (op == IMAGE_PROPERTY_CORNER_RADIUS && ((double *)args)[0] != xrimg->base.corner_radius) { diff --git a/src/common.h b/src/common.h index 35316e10..f92803ae 100644 --- a/src/common.h +++ b/src/common.h @@ -186,7 +186,7 @@ typedef struct session { /// Picture of the root window background. paint_t root_tile_paint; /// The backend data the root pixmap bound to - void *root_image; + image_handle root_image; /// A region of the size of the screen. region_t screen_reg; /// Picture of root window. Destination of painting in no-DBE painting diff --git a/src/win.h b/src/win.h index 93f10b15..bd328806 100644 --- a/src/win.h +++ b/src/win.h @@ -100,9 +100,9 @@ struct managed_win { struct win base; /// backend data attached to this window. Only available when /// `state` is not UNMAPPED - void *win_image; - void *shadow_image; - void *mask_image; + image_handle win_image; + image_handle shadow_image; + image_handle mask_image; /// Pointer to the next higher window to paint. struct managed_win *prev_trans; /// Number of windows above this window