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;
};
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);

View File

@ -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(&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);
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);
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;
}

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,
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);

View File

@ -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,

View File

@ -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);
}

View File

@ -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);

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
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) {

View File

@ -6,6 +6,7 @@
#include <string.h>
#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);
/**

View File

@ -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);

View File

@ -359,10 +359,12 @@ compose_impl(struct _xrender_data *xd, struct xrender_image *xrimg, coord_t dst,
pixman_region32_fini(&reg);
}
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) {

View File

@ -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

View File

@ -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