1
0
Fork 0
mirror of https://github.com/yshui/picom.git synced 2024-10-27 05:24:17 -04:00

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 <msolovyov@protonmail.com>
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui 2024-02-10 08:20:10 +00:00
parent 7f3f8b37b5
commit 2d98518b7d
No known key found for this signature in database
GPG key ID: D3A4405BE6CC17F4
12 changed files with 177 additions and 146 deletions

View file

@ -115,6 +115,10 @@ struct dual_kawase_blur_args {
int strength; int strength;
}; };
typedef struct {
// Intentionally left blank
} *image_handle;
struct backend_operations { struct backend_operations {
// =========== Initialization =========== // =========== Initialization ===========
@ -167,26 +171,27 @@ struct backend_operations {
* Paint the content of an image onto the rendering buffer. * Paint the content of an image onto the rendering buffer.
* *
* @param backend_data the backend data * @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 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 * @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_paint the clip region, in target coordinates
* @param reg_visible the visible 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 (*compose)(backend_t *backend_data, image_handle image, coord_t image_dst,
void *mask, coord_t mask_dst, const region_t *reg_paint, image_handle mask, coord_t mask_dst, const region_t *reg_paint,
const region_t *reg_visible); const region_t *reg_visible) attr_nonnull(1, 2, 6, 7);
/// Fill rectangle of the rendering buffer, mostly for debug purposes, optional. /// Fill rectangle of the rendering buffer, mostly for debug purposes, optional.
void (*fill)(backend_t *backend_data, struct color, const region_t *clip); void (*fill)(backend_t *backend_data, struct color, const region_t *clip);
/// Blur a given region of the rendering buffer. /// Blur a given region of the rendering buffer.
/// ///
/// The blur is limited by `mask`. `mask_dst` specifies the top left corner of the /// The blur can be limited by `mask`. `mask_dst` specifies the top left corner of
/// mask is. /// the mask. `mask` can be NULL.
bool (*blur)(backend_t *backend_data, double opacity, void *blur_ctx, void *mask, bool (*blur)(backend_t *backend_data, double opacity, void *blur_ctx,
coord_t mask_dst, const region_t *reg_blur, image_handle mask, coord_t mask_dst, const region_t *reg_blur,
const region_t *reg_visible) attr_nonnull(1, 3, 6, 7); const region_t *reg_visible) attr_nonnull(1, 3, 6, 7);
/// Update part of the back buffer with the rendering buffer, then present the /// 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. * Bind a X pixmap to the backend's internal image data structure.
* *
* @param backend_data backend data * @param backend_data backend data
* @param pixmap X pixmap to bind * @param pixmap X pixmap to bind
* @param fmt information of the pixmap's visual * @param fmt information of the pixmap's visual
* @param owned whether the ownership of the pixmap is transferred to the backend * @param owned whether the ownership of the pixmap is transferred to the
* @return backend internal data structure bound with this pixmap * backend.
* @return backend specific image handle for the pixmap. May be
* NULL.
*/ */
void *(*bind_pixmap)(backend_t *backend_data, xcb_pixmap_t pixmap, image_handle (*bind_pixmap)(backend_t *backend_data, xcb_pixmap_t pixmap,
struct xvisual_info fmt, bool owned); struct xvisual_info fmt, bool owned);
/// Create a shadow context for rendering shadows with radius `radius`. /// Create a shadow context for rendering shadows with radius `radius`.
/// Default implementation: default_create_shadow_context /// Default implementation: default_create_shadow_context
@ -224,17 +231,23 @@ struct backend_operations {
/// shadow context is created. /// shadow context is created.
/// Default implementation: default_render_shadow /// Default implementation: default_render_shadow
/// ///
/// @return the shadow image, may be NULL.
///
/// Required. /// Required.
void *(*render_shadow)(backend_t *backend_data, int width, int height, image_handle (*render_shadow)(backend_t *backend_data, int width, int height,
struct backend_shadow_context *ctx, struct color color); struct backend_shadow_context *ctx, struct color color);
/// Create a shadow by blurring a mask. `size` is the size of the blur. The /// 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 /// backend can use whichever blur method is the fastest. The shadow produced
/// shoule be consistent with `render_shadow`. /// shoule be consistent with `render_shadow`.
/// ///
/// @param mask the input mask, must not be NULL.
/// @return the shadow image, may be NULL.
///
/// Optional. /// Optional.
void *(*shadow_from_mask)(backend_t *backend_data, void *mask, image_handle (*shadow_from_mask)(backend_t *backend_data, image_handle mask,
struct backend_shadow_context *ctx, struct color color); struct backend_shadow_context *ctx,
struct color color);
/// Create a mask image from region `reg`. This region can be used to create /// 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 /// 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 /// and outside of the mask. Corner radius should exclude the corners from the
/// mask. Corner radius should be applied before the inversion. /// mask. Corner radius should be applied before the inversion.
/// ///
/// @return the mask image, may be NULL.
///
/// Required. /// 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 =========== // ============ Resource management ===========
/// Free resources associated with an image data structure /// 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. /// 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 /// 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 /// window (e.g. when using a custom shader with the glx backend), so only the
/// backend knows if an image is transparent. /// 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); attr_nonnull(1, 2);
/// Get the age of the buffer content we are currently rendering on top /// 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 backend_data backend data
* @param prop the property to change * @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 * @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, 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. * Manipulate an image. Image properties are untouched.
* *
* @param backend_data backend data * @param backend_data backend data
* @param op the operation to perform * @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 * @param reg_op the clip region, define the part of the image to be
* operated on. * operated on.
* @param reg_visible define the part of the image that will eventually * @param reg_visible define the part of the image that will eventually
* be visible on target. this is a hint to the backend * be visible on target. this is a hint to the backend
* for optimization purposes. * for optimization purposes.
* @param args extra arguments, operation specific * @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, bool (*image_op)(backend_t *backend_data, enum image_operations op,
const region_t *reg_op, const region_t *reg_visible, void *args); 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 /// inherits its content and all image properties from the image being
/// cloned. All `image_op` and `set_image_property` calls on the /// cloned. All `image_op` and `set_image_property` calls on the
/// returned image should not affect the original image. /// 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` /// Create a blur context that can be used to call `blur`
void *(*create_blur_context)(backend_t *base, enum blur_method, void *args); void *(*create_blur_context)(backend_t *base, enum blur_method, void *args);

View file

@ -293,8 +293,8 @@ shadow_picture_err:
return false; return false;
} }
void *default_render_shadow(backend_t *backend_data, int width, int height, image_handle default_render_shadow(backend_t *backend_data, int width, int height,
struct backend_shadow_context *sctx, struct color color) { struct backend_shadow_context *sctx, struct color color) {
const conv *kernel = (void *)sctx; const conv *kernel = (void *)sctx;
xcb_render_picture_t shadow_pixel = xcb_render_picture_t shadow_pixel =
solid_picture(backend_data->c, true, 1, color.red, color.green, color.blue); 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); 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); 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, pict);
x_free_picture(backend_data->c, shadow_pixel); 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 /// Implement render_shadow with shadow_from_mask
void * image_handle
backend_render_shadow_from_mask(backend_t *backend_data, int width, int height, 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 *sctx, struct color color) {
region_t reg; region_t reg;
pixman_region32_init_rect(&reg, 0, 0, (unsigned int)width, (unsigned int)height); pixman_region32_init_rect(&reg, 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}, &reg); backend_data, (geometry_t){.width = width, .height = height}, &reg);
pixman_region32_fini(&reg); pixman_region32_fini(&reg);
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); backend_data->ops->release_image(backend_data, mask);
return shadow; return shadow;
} }
@ -458,17 +458,17 @@ struct dual_kawase_params *generate_dual_kawase_params(void *args) {
return params; return params;
} }
void *default_clone_image(backend_t *base attr_unused, const void *image_data, image_handle default_clone_image(backend_t *base attr_unused, image_handle image,
const region_t *reg_visible attr_unused) { const region_t *reg_visible attr_unused) {
auto new_img = ccalloc(1, struct backend_image); 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++; 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, 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 *tex = image_data; auto tex = (struct backend_image *)image;
int *iargs = arg; int *iargs = arg;
bool *bargs = arg; bool *bargs = arg;
double *dargs = arg; double *dargs = arg;
@ -490,8 +490,8 @@ bool default_set_image_property(backend_t *base attr_unused, enum image_properti
return true; return true;
} }
bool default_is_image_transparent(backend_t *base attr_unused, void *image_data) { bool default_is_image_transparent(backend_t *base attr_unused, image_handle image) {
struct backend_image *img = image_data; auto img = (struct backend_image *)image;
return img->opacity < 1 || img->inner->has_alpha; return img->opacity < 1 || img->inner->has_alpha;
} }

View file

@ -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, xcb_image_t *make_shadow(struct x_connection *c, const conv *kernel, double opacity,
int width, int height); int width, int height);
void *default_render_shadow(backend_t *backend_data, int width, int height, image_handle default_render_shadow(backend_t *backend_data, int width, int height,
struct backend_shadow_context *sctx, struct color color); struct backend_shadow_context *sctx, struct color color);
/// Implement `render_shadow` with `shadow_from_mask`. /// Implement `render_shadow` with `shadow_from_mask`.
void * image_handle
backend_render_shadow_from_mask(backend_t *backend_data, int width, int height, 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 *sctx, struct color color);
struct backend_shadow_context * 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 conv **generate_blur_kernel(enum blur_method method, void *args, int *kernel_count);
struct dual_kawase_params *generate_dual_kawase_params(void *args); 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); 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, void *image_data); 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, 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); struct backend_image *default_new_backend_image(int w, int h);

View file

@ -50,8 +50,9 @@ void dummy_deinit(struct backend_base *data) {
free(dummy); 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 dummy = (struct dummy_data *)base;
auto img = (struct dummy_image *)image;
if (img == (struct dummy_image *)&dummy->mask) { if (img == (struct dummy_image *)&dummy->mask) {
return; return;
} }
@ -64,13 +65,13 @@ static void dummy_check_image(struct backend_base *base, const struct dummy_imag
assert(*tmp->refcount > 0); assert(*tmp->refcount > 0);
} }
void dummy_compose(struct backend_base *base, void *image, coord_t dst attr_unused, void dummy_compose(struct backend_base *base, image_handle image, coord_t dst attr_unused,
void *mask attr_unused, coord_t mask_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_paint attr_unused,
const region_t *reg_visible attr_unused) { const region_t *reg_visible attr_unused) {
auto dummy attr_unused = (struct dummy_data *)base; auto dummy attr_unused = (struct dummy_data *)base;
dummy_check_image(base, image); 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, 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, 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, coord_t mask_dst attr_unused, const region_t *reg_blur attr_unused,
const region_t *reg_visible attr_unused) { const region_t *reg_visible attr_unused) {
return true; return true;
} }
void *dummy_bind_pixmap(struct backend_base *base, xcb_pixmap_t pixmap, image_handle dummy_bind_pixmap(struct backend_base *base, xcb_pixmap_t pixmap,
struct xvisual_info fmt, bool owned) { struct xvisual_info fmt, bool owned) {
auto dummy = (struct dummy_data *)base; auto dummy = (struct dummy_data *)base;
struct dummy_image *img = NULL; struct dummy_image *img = NULL;
HASH_FIND_INT(dummy->images, &pixmap, img); HASH_FIND_INT(dummy->images, &pixmap, img);
if (img) { if (img) {
(*img->refcount)++; (*img->refcount)++;
return img; return (image_handle)img;
} }
img = ccalloc(1, struct dummy_image); 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; img->owned = owned;
HASH_ADD_INT(dummy->images, pixmap, img); 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; auto dummy = (struct dummy_data *)base;
if (image == &dummy->mask) { if ((struct backend_image *)image == &dummy->mask) {
return; return;
} }
auto img = (struct dummy_image *)image; 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) { bool dummy_is_image_transparent(struct backend_base *base, image_handle image) {
auto img = (struct dummy_image *)image; dummy_check_image(base, image);
dummy_check_image(base, img); return ((struct dummy_image *)image)->transparent;
return img->transparent;
} }
int dummy_buffer_age(struct backend_base *base attr_unused) { 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, 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) { const region_t *reg_visible attr_unused, void *args attr_unused) {
dummy_check_image(base, image); dummy_check_image(base, image);
return true; return true;
} }
void *dummy_make_mask(struct backend_base *base, geometry_t size attr_unused, image_handle dummy_make_mask(struct backend_base *base, geometry_t size attr_unused,
const region_t *reg attr_unused) { const region_t *reg attr_unused) {
return &(((struct dummy_data *)base)->mask); 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, 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); dummy_check_image(base, image);
return true; return true;
} }
void *dummy_clone_image(struct backend_base *base, const void *image, image_handle dummy_clone_image(struct backend_base *base, image_handle image,
const region_t *reg_visible attr_unused) { const region_t *reg_visible attr_unused) {
auto img = (const struct dummy_image *)image; dummy_check_image(base, image);
dummy_check_image(base, img); auto image_impl = (struct dummy_image *)image;
(*img->refcount)++; (*image_impl->refcount)++;
return (void *)img; return image;
} }
void *dummy_create_blur_context(struct backend_base *base attr_unused, void *dummy_create_blur_context(struct backend_base *base attr_unused,

View file

@ -256,10 +256,11 @@ bool gl_dual_kawase_blur(double opacity, struct gl_blur_context *bctx, const rec
return true; return true;
} }
bool gl_blur_impl(double opacity, struct gl_blur_context *bctx, void *mask, coord_t mask_dst, bool gl_blur_impl(double opacity, struct gl_blur_context *bctx,
const region_t *reg_blur, const region_t *reg_visible attr_unused, struct backend_image *mask, coord_t mask_dst, const region_t *reg_blur,
GLuint source_texture, geometry_t source_size, GLuint target_fbo, const region_t *reg_visible attr_unused, GLuint source_texture,
GLuint default_mask, bool high_precision) { geometry_t source_size, GLuint target_fbo, GLuint default_mask,
bool high_precision) {
bool ret = false; bool ret = false;
if (source_size.width != bctx->fb_width || source_size.height != bctx->fb_height) { 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; 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) { const region_t *reg_blur, const region_t *reg_visible attr_unused) {
auto gd = (struct gl_data *)base; auto gd = (struct gl_data *)base;
auto bctx = (struct gl_blur_context *)ctx; auto bctx = (struct gl_blur_context *)ctx;
return gl_blur_impl(opacity, bctx, mask, mask_dst, reg_blur, reg_visible, return gl_blur_impl(opacity, bctx, (struct backend_image *)mask, mask_dst,
gd->back_texture, reg_blur, reg_visible, gd->back_texture,
(geometry_t){.width = gd->width, .height = gd->height}, (geometry_t){.width = gd->width, .height = gd->height},
gd->back_fbo, gd->default_mask_texture, gd->dithered_present); gd->back_fbo, gd->default_mask_texture, gd->dithered_present);
} }

View file

@ -249,7 +249,7 @@ end:
return &gd->gl.base; 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) { egl_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, bool owned) {
struct egl_data *gd = (void *)base; struct egl_data *gd = (void *)base;
struct egl_pixmap *eglpixmap = NULL; 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); glBindTexture(GL_TEXTURE_2D, 0);
gl_check_err(); gl_check_err();
return wd; return (image_handle)wd;
err: err:
if (eglpixmap && eglpixmap->image) { if (eglpixmap && eglpixmap->image) {
eglDestroyImage(gd->display, eglpixmap->image); eglDestroyImage(gd->display, eglpixmap->image);

View file

@ -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 // TODO(yshui) make use of reg_visible
void gl_compose(backend_t *base, void *image_data, coord_t image_dst, void *mask, void gl_compose(backend_t *base, image_handle image, coord_t image_dst,
coord_t mask_dst, const region_t *reg_tgt, image_handle mask_, coord_t mask_dst, const region_t *reg_tgt,
const region_t *reg_visible attr_unused) { const region_t *reg_visible attr_unused) {
auto gd = (struct gl_data *)base; 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; auto inner = (struct gl_texture *)img->inner;
// Painting // 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); 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 tex = ccalloc(1, struct gl_texture);
auto img = default_new_backend_image(size.width, size.height); auto img = default_new_backend_image(size.width, size.height);
tex->width = size.width; 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); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &fbo); glDeleteFramebuffers(1, &fbo);
return img; return (image_handle)img;
} }
static void gl_release_image_inner(backend_t *base, struct gl_texture *inner) { 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(); gl_check_err();
} }
void gl_release_image(backend_t *base, void *image_data) { void gl_release_image(backend_t *base, image_handle image) {
struct backend_image *wd = image_data; auto wd = (struct backend_image *)image;
auto inner = (struct gl_texture *)wd->inner; auto inner = (struct gl_texture *)wd->inner;
inner->refcount--; inner->refcount--;
assert(inner->refcount >= 0); assert(inner->refcount >= 0);
@ -1221,9 +1222,9 @@ bool gl_last_render_time(backend_t *base, struct timespec *ts) {
return true; 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) { 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) { switch (op) {
case IMAGE_OP_APPLY_ALPHA: case IMAGE_OP_APPLY_ALPHA:
gl_image_decouple(base, tex); 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, 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) { 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; auto inner = (struct gl_texture *)img->inner;
inner->shader = args; inner->shader = args;
return true; return true;
@ -1280,12 +1281,12 @@ void gl_destroy_shadow_context(backend_t *base attr_unused, struct backend_shado
free(ctx_); free(ctx_);
} }
void *gl_shadow_from_mask(backend_t *base, void *mask, image_handle gl_shadow_from_mask(backend_t *base, image_handle mask_,
struct backend_shadow_context *sctx, struct color color) { struct backend_shadow_context *sctx, struct color color) {
log_debug("Create shadow from mask"); log_debug("Create shadow from mask");
auto gd = (struct gl_data *)base; auto gd = (struct gl_data *)base;
auto img = (struct backend_image *)mask; auto mask = (struct backend_image *)mask_;
auto inner = (struct gl_texture *)img->inner; auto inner = (struct gl_texture *)mask->inner;
auto gsctx = (struct gl_shadow_context *)sctx; auto gsctx = (struct gl_shadow_context *)sctx;
int radius = (int)gsctx->radius; 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, glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
source_texture, 0); source_texture, 0);
glDrawBuffer(GL_COLOR_ATTACHMENT0); 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 // If the mask is inverted, clear the source_texture to white, so the
// "outside" of the mask would be correct // "outside" of the mask would be correct
glClearColor(1, 1, 1, 1); glClearColor(1, 1, 1, 1);
@ -1424,7 +1425,7 @@ void *gl_shadow_from_mask(backend_t *base, void *mask,
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &fbo); glDeleteFramebuffers(1, &fbo);
gl_check_err(); gl_check_err();
return new_img; return (image_handle)new_img;
} }
enum device_status gl_device_status(backend_t *base) { enum device_status gl_device_status(backend_t *base) {

View file

@ -6,6 +6,7 @@
#include <string.h> #include <string.h>
#include "backend/backend.h" #include "backend/backend.h"
#include "backend/backend_common.h"
#include "log.h" #include "log.h"
#include "region.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); void gl_destroy_window_shader(backend_t *backend_data, void *shader);
uint64_t gl_get_shader_attributes(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, 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); bool gl_last_render_time(backend_t *backend_data, struct timespec *time);
/** /**
* @brief Render a region with texture data. * @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); coord_t mask_dst, const region_t *reg_tgt, const region_t *reg_visible);
void gl_resize(struct gl_data *, int width, int height); 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); 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); const region_t *reg_op, const region_t *reg_visible, void *arg);
void gl_release_image(backend_t *base, void *image_data); void gl_release_image(backend_t *base, image_handle image);
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);
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, bool gl_blur(backend_t *base, double opacity, void *ctx, image_handle mask,
const region_t *reg_blur, const region_t *reg_visible); 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, bool gl_blur_impl(double opacity, struct gl_blur_context *bctx,
const region_t *reg_blur, const region_t *reg_visible attr_unused, struct backend_image *mask, coord_t mask_dst, const region_t *reg_blur,
GLuint source_texture, geometry_t source_size, GLuint target_fbo, const region_t *reg_visible attr_unused, GLuint source_texture,
GLuint default_mask, bool high_precision); 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_create_blur_context(backend_t *base, enum blur_method, void *args);
void gl_destroy_blur_context(backend_t *base, void *ctx); void gl_destroy_blur_context(backend_t *base, void *ctx);
struct backend_shadow_context *gl_create_shadow_context(backend_t *base, double radius); 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_destroy_shadow_context(backend_t *base attr_unused, struct backend_shadow_context *ctx);
void *gl_shadow_from_mask(backend_t *base, void *mask, image_handle gl_shadow_from_mask(backend_t *base, image_handle mask,
struct backend_shadow_context *sctx, struct color color); struct backend_shadow_context *sctx, struct color color);
void gl_get_blur_size(void *blur_context, int *width, int *height); 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_fill(backend_t *base, struct color, const region_t *clip);
void gl_present(backend_t *base, const region_t *); 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); enum device_status gl_device_status(backend_t *base);
/** /**

View file

@ -380,7 +380,7 @@ end:
return &gd->gl.base; 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) { glx_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, bool owned) {
struct _glx_pixmap *glxpixmap = NULL; struct _glx_pixmap *glxpixmap = NULL;
auto gd = (struct _glx_data *)base; 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); glBindTexture(GL_TEXTURE_2D, 0);
gl_check_err(); gl_check_err();
return wd; return (image_handle)wd;
err: err:
if (glxpixmap && glxpixmap->glpixmap) { if (glxpixmap && glxpixmap->glpixmap) {
glXDestroyPixmap(base->c->dpy, glxpixmap->glpixmap); glXDestroyPixmap(base->c->dpy, glxpixmap->glpixmap);

View file

@ -359,10 +359,12 @@ compose_impl(struct _xrender_data *xd, struct xrender_image *xrimg, coord_t dst,
pixman_region32_fini(&reg); pixman_region32_fini(&reg);
} }
static void compose(backend_t *base, void *img_data, coord_t dst, void *mask, coord_t mask_dst, static void compose(backend_t *base, image_handle image_, coord_t dst, image_handle mask_,
const region_t *reg_paint, const region_t *reg_visible) { coord_t mask_dst, const region_t *reg_paint, const region_t *reg_visible) {
struct _xrender_data *xd = (void *)base; 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]); 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)}}); .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) { 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) { if (bctx->method == BLUR_METHOD_NONE) {
return true; return true;
} }
@ -517,7 +520,7 @@ static bool blur(backend_t *backend_data, double opacity, void *ctx_, void *mask
return true; return true;
} }
static void * static image_handle
bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, bool owned) { bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, bool owned) {
xcb_generic_error_t *e; xcb_generic_error_t *e;
auto r = xcb_get_geometry_reply(base->c->c, xcb_get_geometry(base->c->c, pixmap), &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); free(img);
return NULL; return NULL;
} }
return img; return (image_handle)img;
} }
static void release_image_inner(backend_t *base, struct _xrender_image_data_inner *inner) { static void release_image_inner(backend_t *base, struct _xrender_image_data_inner *inner) {
x_free_picture(base->c, inner->pict); 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) { static void release_image(backend_t *base, image_handle image) {
struct xrender_image *img = image; auto img = (struct xrender_image *)image;
release_rounded_corner_cache(base, img->rounded_rectangle); release_rounded_corner_cache(base, img->rounded_rectangle);
img->rounded_rectangle = NULL; img->rounded_rectangle = NULL;
img->base.inner->refcount -= 1; img->base.inner->refcount -= 1;
if (img->base.inner->refcount == 0) { 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); 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; 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; struct _xrender_data *xd = (void *)base;
// Give the mask a 1 pixel wide border to emulate the clamp to border behavior of // Give the mask a 1 pixel wide border to emulate the clamp to border behavior of
// OpenGL textures. // 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.dim = 0;
img->base.inner = (struct backend_image_inner_base *)inner; img->base.inner = (struct backend_image_inner_base *)inner;
img->rounded_rectangle = NULL; 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) { 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; 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) { const region_t *reg_op, const region_t *reg_visible, void *arg) {
struct _xrender_data *xd = (void *)base; struct _xrender_data *xd = (void *)base;
struct backend_image *img = image; auto img = (struct backend_image *)image;
region_t reg; region_t reg;
double *dargs = arg; double *dargs = arg;
@ -964,19 +967,19 @@ err:
return NULL; return NULL;
} }
void *clone_image(backend_t *base attr_unused, const void *image_data, image_handle clone_image(backend_t *base attr_unused, image_handle image,
const region_t *reg_visible attr_unused) { const region_t *reg_visible attr_unused) {
auto new_img = ccalloc(1, struct xrender_image); 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++; new_img->base.inner->refcount++;
if (new_img->rounded_rectangle) { if (new_img->rounded_rectangle) {
new_img->rounded_rectangle->refcount++; new_img->rounded_rectangle->refcount++;
} }
return new_img; return (image_handle)new_img;
} }
static bool static bool set_image_property(backend_t *base, enum image_properties op,
set_image_property(backend_t *base, enum image_properties op, void *image, void *args) { image_handle image, void *args) {
auto xrimg = (struct xrender_image *)image; auto xrimg = (struct xrender_image *)image;
if (op == IMAGE_PROPERTY_CORNER_RADIUS && if (op == IMAGE_PROPERTY_CORNER_RADIUS &&
((double *)args)[0] != xrimg->base.corner_radius) { ((double *)args)[0] != xrimg->base.corner_radius) {

View file

@ -186,7 +186,7 @@ typedef struct session {
/// Picture of the root window background. /// Picture of the root window background.
paint_t root_tile_paint; paint_t root_tile_paint;
/// The backend data the root pixmap bound to /// The backend data the root pixmap bound to
void *root_image; image_handle root_image;
/// A region of the size of the screen. /// A region of the size of the screen.
region_t screen_reg; region_t screen_reg;
/// Picture of root window. Destination of painting in no-DBE painting /// Picture of root window. Destination of painting in no-DBE painting

View file

@ -100,9 +100,9 @@ struct managed_win {
struct win base; struct win base;
/// backend data attached to this window. Only available when /// backend data attached to this window. Only available when
/// `state` is not UNMAPPED /// `state` is not UNMAPPED
void *win_image; image_handle win_image;
void *shadow_image; image_handle shadow_image;
void *mask_image; image_handle mask_image;
/// Pointer to the next higher window to paint. /// Pointer to the next higher window to paint.
struct managed_win *prev_trans; struct managed_win *prev_trans;
/// Number of windows above this window /// Number of windows above this window