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:
parent
7f3f8b37b5
commit
2d98518b7d
12 changed files with 177 additions and 146 deletions
|
@ -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
|
||||
|
@ -204,10 +209,12 @@ struct backend_operations {
|
|||
* @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 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,
|
||||
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`.
|
||||
|
@ -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,
|
||||
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,19 +331,19 @@ 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
|
||||
*/
|
||||
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
|
||||
|
@ -332,15 +352,18 @@ struct backend_operations {
|
|||
* @param args extra arguments, operation specific
|
||||
* @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);
|
||||
|
|
|
@ -293,7 +293,7 @@ shadow_picture_err:
|
|||
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) {
|
||||
const conv *kernel = (void *)sctx;
|
||||
xcb_render_picture_t shadow_pixel =
|
||||
|
@ -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,
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
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);
|
||||
|
|
|
@ -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,
|
||||
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,
|
||||
image_handle dummy_make_mask(struct backend_base *base, geometry_t size 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,
|
||||
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,
|
||||
image_handle dummy_clone_image(struct backend_base *base, image_handle 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;
|
||||
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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
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) {
|
||||
|
|
|
@ -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,
|
||||
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);
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue