Merge pull request #1208 from absolutelynothelix/we-do-a-little-bit-of-refactoring

This commit is contained in:
Yuxuan Shui 2024-02-29 05:50:11 +00:00 committed by GitHub
commit f14149d6cd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 102 additions and 97 deletions

View File

@ -24,7 +24,7 @@
#include "win.h" #include "win.h"
#include "x.h" #include "x.h"
typedef struct _xrender_data { typedef struct xrender_data {
backend_t base; backend_t base;
/// If vsync is enabled and supported by the current system /// If vsync is enabled and supported by the current system
bool vsync; bool vsync;
@ -62,7 +62,7 @@ typedef struct _xrender_data {
xcb_xfixes_region_t present_region; xcb_xfixes_region_t present_region;
} xrender_data; } xrender_data;
struct _xrender_blur_context { struct xrender_blur_context {
enum blur_method method; enum blur_method method;
/// Blur kernels converted to X format /// Blur kernels converted to X format
struct x_convolution_kernel **x_blur_kernel; struct x_convolution_kernel **x_blur_kernel;
@ -73,7 +73,7 @@ struct _xrender_blur_context {
int x_blur_kernel_count; int x_blur_kernel_count;
}; };
struct _xrender_image_data_inner { struct xrender_image_data_inner {
// struct backend_image_inner_base // struct backend_image_inner_base
int refcount; int refcount;
bool has_alpha; bool has_alpha;
@ -107,8 +107,8 @@ struct xrender_image {
/// Make a picture of size width x height, which has a rounded rectangle of corner_radius /// Make a picture of size width x height, which has a rounded rectangle of corner_radius
/// rendered in it. /// rendered in it.
struct xrender_rounded_rectangle_cache * struct xrender_rounded_rectangle_cache *
make_rounded_corner_cache(struct x_connection *c, xcb_render_picture_t src, int width, xrender_make_rounded_corner_cache(struct x_connection *c, xcb_render_picture_t src,
int height, int corner_radius) { int width, int height, int corner_radius) {
auto picture = x_create_picture_with_standard(c, width, height, auto picture = x_create_picture_with_standard(c, width, height,
XCB_PICT_STANDARD_ARGB_32, 0, NULL); XCB_PICT_STANDARD_ARGB_32, 0, NULL);
if (picture == XCB_NONE) { if (picture == XCB_NONE) {
@ -173,9 +173,10 @@ make_rounded_corner_cache(struct x_connection *c, xcb_render_picture_t src, int
return ret; return ret;
} }
static xcb_render_picture_t process_mask(struct _xrender_data *xd, struct xrender_image *mask, static xcb_render_picture_t
xcb_render_picture_t alpha_pict, bool *allocated) { xrender_process_mask(struct xrender_data *xd, struct xrender_image *mask,
auto inner = (struct _xrender_image_data_inner *)mask->base.inner; xcb_render_picture_t alpha_pict, bool *allocated) {
auto inner = (struct xrender_image_data_inner *)mask->base.inner;
if (!mask->base.color_inverted && mask->base.corner_radius == 0) { if (!mask->base.color_inverted && mask->base.corner_radius == 0) {
*allocated = false; *allocated = false;
return inner->pict; return inner->pict;
@ -192,7 +193,7 @@ static xcb_render_picture_t process_mask(struct _xrender_data *xd, struct xrende
// Remember: the mask has a 1-pixel border // Remember: the mask has a 1-pixel border
if (mask->base.corner_radius != 0) { if (mask->base.corner_radius != 0) {
if (mask->rounded_rectangle == NULL) { if (mask->rounded_rectangle == NULL) {
mask->rounded_rectangle = make_rounded_corner_cache( mask->rounded_rectangle = xrender_make_rounded_corner_cache(
xd->base.c, xd->white_pixel, inner->width - 2, xd->base.c, xd->white_pixel, inner->width - 2,
inner->height - 2, (int)mask->base.corner_radius); inner->height - 2, (int)mask->base.corner_radius);
} }
@ -215,18 +216,18 @@ static xcb_render_picture_t process_mask(struct _xrender_data *xd, struct xrende
return ret; return ret;
} }
static void static void xrender_compose_impl(struct xrender_data *xd, struct xrender_image *xrimg,
compose_impl(struct _xrender_data *xd, struct xrender_image *xrimg, coord_t dst, coord_t dst, struct xrender_image *mask, coord_t mask_dst,
struct xrender_image *mask, coord_t mask_dst, const region_t *reg_paint, const region_t *reg_paint, const region_t *reg_visible,
const region_t *reg_visible, xcb_render_picture_t result) { xcb_render_picture_t result) {
const struct backend_image *img = &xrimg->base; const struct backend_image *img = &xrimg->base;
bool mask_allocated = false; bool mask_allocated = false;
auto mask_pict = xd->alpha_pict[(int)(img->opacity * MAX_ALPHA)]; auto mask_pict = xd->alpha_pict[(int)(img->opacity * MAX_ALPHA)];
if (mask != NULL) { if (mask != NULL) {
mask_pict = process_mask( mask_pict = xrender_process_mask(
xd, mask, img->opacity < 1.0 ? mask_pict : XCB_NONE, &mask_allocated); xd, mask, img->opacity < 1.0 ? mask_pict : XCB_NONE, &mask_allocated);
} }
auto inner = (struct _xrender_image_data_inner *)img->inner; auto inner = (struct xrender_image_data_inner *)img->inner;
region_t reg; region_t reg;
bool has_alpha = inner->has_alpha || img->opacity != 1; bool has_alpha = inner->has_alpha || img->opacity != 1;
@ -248,9 +249,9 @@ compose_impl(struct _xrender_data *xd, struct xrender_image *xrimg, coord_t dst,
pixman_region32_intersect(&reg, (region_t *)reg_paint, (region_t *)reg_visible); pixman_region32_intersect(&reg, (region_t *)reg_paint, (region_t *)reg_visible);
x_set_picture_clip_region(xd->base.c, result, 0, 0, &reg); x_set_picture_clip_region(xd->base.c, result, 0, 0, &reg);
if (img->corner_radius != 0 && xrimg->rounded_rectangle == NULL) { if (img->corner_radius != 0 && xrimg->rounded_rectangle == NULL) {
xrimg->rounded_rectangle = xrimg->rounded_rectangle = xrender_make_rounded_corner_cache(
make_rounded_corner_cache(xd->base.c, xd->white_pixel, inner->width, xd->base.c, xd->white_pixel, inner->width, inner->height,
inner->height, (int)img->corner_radius); (int)img->corner_radius);
} }
if (((img->color_inverted || img->dim != 0) && has_alpha) || img->corner_radius != 0) { if (((img->color_inverted || img->dim != 0) && has_alpha) || img->corner_radius != 0) {
// Apply image properties using a temporary image, because the source // Apply image properties using a temporary image, because the source
@ -359,17 +360,18 @@ 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, image_handle image_, coord_t dst, image_handle mask_, static void
coord_t mask_dst, const region_t *reg_paint, const region_t *reg_visible) { xrender_compose(backend_t *base, image_handle image_, coord_t dst, image_handle mask_,
struct _xrender_data *xd = (void *)base; coord_t mask_dst, const region_t *reg_paint, const region_t *reg_visible) {
auto xd = (struct xrender_data *)base;
auto image = (struct xrender_image *)image_; auto image = (struct xrender_image *)image_;
auto mask = (struct xrender_image *)mask_; auto mask = (struct xrender_image *)mask_;
return compose_impl(xd, image, dst, mask, mask_dst, reg_paint, reg_visible, return xrender_compose_impl(xd, image, dst, mask, mask_dst, reg_paint,
xd->back[2]); reg_visible, xd->back[2]);
} }
static void fill(backend_t *base, struct color c, const region_t *clip) { static void xrender_fill(backend_t *base, struct color c, const region_t *clip) {
struct _xrender_data *xd = (void *)base; auto xd = (struct xrender_data *)base;
const rect_t *extent = pixman_region32_extents((region_t *)clip); const rect_t *extent = pixman_region32_extents((region_t *)clip);
x_set_picture_clip_region(base->c, xd->back[2], 0, 0, clip); x_set_picture_clip_region(base->c, xd->back[2], 0, 0, clip);
// color is in X fixed point representation // color is in X fixed point representation
@ -386,15 +388,16 @@ 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_, image_handle mask_, static bool
coord_t mask_dst, const region_t *reg_blur, const region_t *reg_visible) { xrender_blur(backend_t *backend_data, double opacity, void *ctx_, image_handle mask_,
auto bctx = (struct _xrender_blur_context *)ctx_; coord_t mask_dst, const region_t *reg_blur, const region_t *reg_visible) {
auto bctx = (struct xrender_blur_context *)ctx_;
auto mask = (struct xrender_image *)mask_; auto mask = (struct xrender_image *)mask_;
if (bctx->method == BLUR_METHOD_NONE) { if (bctx->method == BLUR_METHOD_NONE) {
return true; return true;
} }
struct _xrender_data *xd = (void *)backend_data; auto xd = (struct xrender_data *)backend_data;
auto c = xd->base.c; auto c = xd->base.c;
region_t reg_op; region_t reg_op;
pixman_region32_init(&reg_op); pixman_region32_init(&reg_op);
@ -444,8 +447,8 @@ static bool blur(backend_t *backend_data, double opacity, void *ctx_, image_hand
auto mask_pict = xd->alpha_pict[(int)(opacity * MAX_ALPHA)]; auto mask_pict = xd->alpha_pict[(int)(opacity * MAX_ALPHA)];
bool mask_allocated = false; bool mask_allocated = false;
if (mask != NULL) { if (mask != NULL) {
mask_pict = process_mask(xd, mask, opacity != 1.0 ? mask_pict : XCB_NONE, mask_pict = xrender_process_mask(
&mask_allocated); xd, mask, opacity != 1.0 ? mask_pict : XCB_NONE, &mask_allocated);
} }
int current = 0; int current = 0;
x_set_picture_clip_region(c, src_pict, 0, 0, &reg_op_resized); x_set_picture_clip_region(c, src_pict, 0, 0, &reg_op_resized);
@ -520,8 +523,8 @@ static bool blur(backend_t *backend_data, double opacity, void *ctx_, image_hand
return true; return true;
} }
static image_handle static image_handle xrender_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap,
bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, bool owned) { 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);
if (!r) { if (!r) {
@ -532,7 +535,7 @@ bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, bool
} }
auto img = ccalloc(1, struct xrender_image); auto img = ccalloc(1, struct xrender_image);
auto inner = ccalloc(1, struct _xrender_image_data_inner); auto inner = ccalloc(1, struct xrender_image_data_inner);
inner->depth = (uint8_t)fmt.visual_depth; inner->depth = (uint8_t)fmt.visual_depth;
inner->width = img->base.ewidth = r->width; inner->width = img->base.ewidth = r->width;
inner->height = img->base.eheight = r->height; inner->height = img->base.eheight = r->height;
@ -557,7 +560,8 @@ bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fmt, bool
} }
return (image_handle)img; return (image_handle)img;
} }
static void release_image_inner(backend_t *base, struct _xrender_image_data_inner *inner) { static void
xrender_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);
if (inner->owned) { if (inner->owned) {
xcb_free_pixmap(base->c->c, inner->pixmap); xcb_free_pixmap(base->c->c, inner->pixmap);
@ -566,7 +570,8 @@ static void release_image_inner(backend_t *base, struct _xrender_image_data_inne
} }
static void static void
release_rounded_corner_cache(backend_t *base, struct xrender_rounded_rectangle_cache *cache) { xrender_release_rounded_corner_cache(backend_t *base,
struct xrender_rounded_rectangle_cache *cache) {
if (!cache) { if (!cache) {
return; return;
} }
@ -579,19 +584,20 @@ release_rounded_corner_cache(backend_t *base, struct xrender_rounded_rectangle_c
} }
} }
static void release_image(backend_t *base, image_handle image) { static void xrender_release_image(backend_t *base, image_handle image) {
auto img = (struct xrender_image *)image; auto img = (struct xrender_image *)image;
release_rounded_corner_cache(base, img->rounded_rectangle); xrender_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, (struct _xrender_image_data_inner *)img->base.inner); xrender_release_image_inner(
base, (struct xrender_image_data_inner *)img->base.inner);
} }
free(img); free(img);
} }
static void deinit(backend_t *backend_data) { static void xrender_deinit(backend_t *backend_data) {
struct _xrender_data *xd = (void *)backend_data; auto xd = (struct xrender_data *)backend_data;
for (int i = 0; i < 256; i++) { for (int i = 0; i < 256; i++) {
x_free_picture(xd->base.c, xd->alpha_pict[i]); x_free_picture(xd->base.c, xd->alpha_pict[i]);
} }
@ -613,8 +619,8 @@ static void deinit(backend_t *backend_data) {
free(xd); free(xd);
} }
static void present(backend_t *base, const region_t *region) { static void xrender_present(backend_t *base, const region_t *region) {
struct _xrender_data *xd = (void *)base; auto xd = (struct xrender_data *)base;
const rect_t *extent = pixman_region32_extents((region_t *)region); const rect_t *extent = pixman_region32_extents((region_t *)region);
int16_t orig_x = to_i16_checked(extent->x1), orig_y = to_i16_checked(extent->y1); int16_t orig_x = to_i16_checked(extent->x1), orig_y = to_i16_checked(extent->y1);
uint16_t region_width = to_u16_checked(extent->x2 - extent->x1), uint16_t region_width = to_u16_checked(extent->x2 - extent->x1),
@ -647,8 +653,8 @@ static void present(backend_t *base, const region_t *region) {
return; return;
} }
// TODO(yshui) don't block wait for present completion // TODO(yshui) don't block wait for present completion
xcb_present_generic_event_t *pev = auto pev = (xcb_present_generic_event_t *)xcb_wait_for_special_event(
(void *)xcb_wait_for_special_event(base->c->c, xd->present_event); base->c->c, xd->present_event);
if (!pev) { if (!pev) {
// We don't know what happened, maybe X died // We don't know what happened, maybe X died
// But reset buffer age, so in case we do recover, we will // But reset buffer age, so in case we do recover, we will
@ -657,7 +663,7 @@ static void present(backend_t *base, const region_t *region) {
return; return;
} }
assert(pev->evtype == XCB_PRESENT_COMPLETE_NOTIFY); assert(pev->evtype == XCB_PRESENT_COMPLETE_NOTIFY);
xcb_present_complete_notify_event_t *pcev = (void *)pev; auto pcev = (xcb_present_complete_notify_event_t *)pev;
// log_trace("Present complete: %d %ld", pcev->mode, pcev->msc); // log_trace("Present complete: %d %ld", pcev->mode, pcev->msc);
xd->buffer_age[xd->curr_back] = 1; xd->buffer_age[xd->curr_back] = 1;
@ -678,8 +684,8 @@ static void present(backend_t *base, const region_t *region) {
} }
} }
static int buffer_age(backend_t *backend_data) { static int xrender_buffer_age(backend_t *backend_data) {
struct _xrender_data *xd = (void *)backend_data; auto xd = (struct xrender_data *)backend_data;
if (!xd->vsync) { if (!xd->vsync) {
// Only the target picture really holds the screen content, and its // Only the target picture really holds the screen content, and its
// content is always up to date. So buffer age is always 1. // content is always up to date. So buffer age is always 1.
@ -688,9 +694,9 @@ static int buffer_age(backend_t *backend_data) {
return xd->buffer_age[xd->curr_back]; return xd->buffer_age[xd->curr_back];
} }
static struct _xrender_image_data_inner * static struct xrender_image_data_inner *
new_inner(backend_t *base, int w, int h, xcb_visualid_t visual, uint8_t depth) { xrender_new_inner(backend_t *base, int w, int h, xcb_visualid_t visual, uint8_t depth) {
auto new_inner = ccalloc(1, struct _xrender_image_data_inner); auto new_inner = ccalloc(1, struct xrender_image_data_inner);
new_inner->pixmap = x_create_pixmap(base->c, depth, w, h); new_inner->pixmap = x_create_pixmap(base->c, depth, w, h);
if (new_inner->pixmap == XCB_NONE) { if (new_inner->pixmap == XCB_NONE) {
log_error("Failed to create pixmap for copy"); log_error("Failed to create pixmap for copy");
@ -714,15 +720,15 @@ new_inner(backend_t *base, int w, int h, xcb_visualid_t visual, uint8_t depth) {
return new_inner; return new_inner;
} }
static image_handle make_mask(backend_t *base, geometry_t size, const region_t *reg) { static image_handle xrender_make_mask(backend_t *base, geometry_t size, const region_t *reg) {
struct _xrender_data *xd = (void *)base; auto xd = (struct xrender_data *)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.
auto w16 = to_u16_checked(size.width + 2); auto w16 = to_u16_checked(size.width + 2);
auto h16 = to_u16_checked(size.height + 2); auto h16 = to_u16_checked(size.height + 2);
auto inner = auto inner = xrender_new_inner(
new_inner(base, size.width + 2, size.height + 2, base, size.width + 2, size.height + 2,
x_get_visual_for_standard(base->c, XCB_PICT_STANDARD_ARGB_32), 32); x_get_visual_for_standard(base->c, XCB_PICT_STANDARD_ARGB_32), 32);
xcb_render_change_picture(base->c->c, inner->pict, XCB_RENDER_CP_REPEAT, xcb_render_change_picture(base->c->c, inner->pict, XCB_RENDER_CP_REPEAT,
(uint32_t[]){XCB_RENDER_REPEAT_PAD}); (uint32_t[]){XCB_RENDER_REPEAT_PAD});
const rect_t *extent = pixman_region32_extents((region_t *)reg); const rect_t *extent = pixman_region32_extents((region_t *)reg);
@ -760,17 +766,18 @@ static image_handle make_mask(backend_t *base, geometry_t size, const region_t *
return (image_handle)img; return (image_handle)img;
} }
static bool decouple_image(backend_t *base, struct backend_image *img, const region_t *reg) { static bool
xrender_decouple_image(backend_t *base, struct backend_image *img, const region_t *reg) {
if (img->inner->refcount == 1) { if (img->inner->refcount == 1) {
return true; return true;
} }
auto inner = (struct _xrender_image_data_inner *)img->inner; auto inner = (struct xrender_image_data_inner *)img->inner;
// Force new pixmap to a 32-bit ARGB visual to allow for transparent frames around // Force new pixmap to a 32-bit ARGB visual to allow for transparent frames around
// non-transparent windows // non-transparent windows
auto visual = (inner->depth == 32) auto visual = (inner->depth == 32)
? inner->visual ? inner->visual
: x_get_visual_for_standard(base->c, XCB_PICT_STANDARD_ARGB_32); : x_get_visual_for_standard(base->c, XCB_PICT_STANDARD_ARGB_32);
auto inner2 = new_inner(base, inner->width, inner->height, visual, 32); auto inner2 = xrender_new_inner(base, inner->width, inner->height, visual, 32);
if (!inner2) { if (!inner2) {
return false; return false;
} }
@ -785,9 +792,9 @@ 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, image_handle image, static bool xrender_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; auto xd = (struct xrender_data *)base;
auto img = (struct backend_image *)image; auto img = (struct backend_image *)image;
region_t reg; region_t reg;
double *dargs = arg; double *dargs = arg;
@ -807,12 +814,12 @@ static bool image_op(backend_t *base, enum image_operations op, image_handle ima
break; break;
} }
if (!decouple_image(base, img, reg_visible)) { if (!xrender_decouple_image(base, img, reg_visible)) {
pixman_region32_fini(&reg); pixman_region32_fini(&reg);
return false; return false;
} }
auto inner = (struct _xrender_image_data_inner *)img->inner; auto inner = (struct xrender_image_data_inner *)img->inner;
auto alpha_pict = xd->alpha_pict[(int)((1 - dargs[0]) * MAX_ALPHA)]; auto alpha_pict = xd->alpha_pict[(int)((1 - dargs[0]) * MAX_ALPHA)];
x_set_picture_clip_region(base->c, inner->pict, 0, 0, &reg); x_set_picture_clip_region(base->c, inner->pict, 0, 0, &reg);
xcb_render_composite(base->c->c, XCB_RENDER_PICT_OP_OUT_REVERSE, xcb_render_composite(base->c->c, XCB_RENDER_PICT_OP_OUT_REVERSE,
@ -826,9 +833,9 @@ static bool image_op(backend_t *base, enum image_operations op, image_handle ima
return true; return true;
} }
static void * static void *xrender_create_blur_context(backend_t *base attr_unused,
create_blur_context(backend_t *base attr_unused, enum blur_method method, void *args) { enum blur_method method, void *args) {
auto ret = ccalloc(1, struct _xrender_blur_context); auto ret = ccalloc(1, struct xrender_blur_context);
if (!method || method >= BLUR_METHOD_INVALID) { if (!method || method >= BLUR_METHOD_INVALID) {
ret->method = BLUR_METHOD_NONE; ret->method = BLUR_METHOD_NONE;
return ret; return ret;
@ -870,8 +877,8 @@ create_blur_context(backend_t *base attr_unused, enum blur_method method, void *
return ret; return ret;
} }
static void destroy_blur_context(backend_t *base attr_unused, void *ctx_) { static void xrender_destroy_blur_context(backend_t *base attr_unused, void *ctx_) {
struct _xrender_blur_context *ctx = ctx_; struct xrender_blur_context *ctx = ctx_;
for (int i = 0; i < ctx->x_blur_kernel_count; i++) { for (int i = 0; i < ctx->x_blur_kernel_count; i++) {
free(ctx->x_blur_kernel[i]); free(ctx->x_blur_kernel[i]);
} }
@ -879,18 +886,18 @@ static void destroy_blur_context(backend_t *base attr_unused, void *ctx_) {
free(ctx); free(ctx);
} }
static void get_blur_size(void *blur_context, int *width, int *height) { static void xrender_get_blur_size(void *blur_context, int *width, int *height) {
struct _xrender_blur_context *ctx = blur_context; struct xrender_blur_context *ctx = blur_context;
*width = ctx->resize_width; *width = ctx->resize_width;
*height = ctx->resize_height; *height = ctx->resize_height;
} }
static backend_t *backend_xrender_init(session_t *ps, xcb_window_t target) { static backend_t *xrender_init(session_t *ps, xcb_window_t target) {
if (ps->o.dithered_present) { if (ps->o.dithered_present) {
log_warn("\"dithered-present\" is not supported by the xrender backend."); log_warn("\"dithered-present\" is not supported by the xrender backend.");
} }
auto xd = ccalloc(1, struct _xrender_data); auto xd = ccalloc(1, struct xrender_data);
init_backend_base(&xd->base, ps); init_backend_base(&xd->base, ps);
for (int i = 0; i <= MAX_ALPHA; ++i) { for (int i = 0; i <= MAX_ALPHA; ++i) {
@ -963,12 +970,12 @@ static backend_t *backend_xrender_init(session_t *ps, xcb_window_t target) {
return &xd->base; return &xd->base;
err: err:
deinit(&xd->base); xrender_deinit(&xd->base);
return NULL; return NULL;
} }
image_handle clone_image(backend_t *base attr_unused, image_handle image, image_handle xrender_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; *new_img = *(struct xrender_image *)image;
new_img->base.inner->refcount++; new_img->base.inner->refcount++;
@ -978,41 +985,39 @@ image_handle clone_image(backend_t *base attr_unused, image_handle image,
return (image_handle)new_img; return (image_handle)new_img;
} }
static bool set_image_property(backend_t *base, enum image_properties op, static bool xrender_set_image_property(backend_t *base, enum image_properties op,
image_handle 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) {
// Free cached rounded rectangle if corner radius changed // Free cached rounded rectangle if corner radius changed
release_rounded_corner_cache(base, xrimg->rounded_rectangle); xrender_release_rounded_corner_cache(base, xrimg->rounded_rectangle);
xrimg->rounded_rectangle = NULL; xrimg->rounded_rectangle = NULL;
} }
return default_set_image_property(base, op, image, args); return default_set_image_property(base, op, image, args);
} }
struct backend_operations xrender_ops = { struct backend_operations xrender_ops = {
.init = backend_xrender_init, .init = xrender_init,
.deinit = deinit, .deinit = xrender_deinit,
.blur = blur, .compose = xrender_compose,
.present = present, .fill = xrender_fill,
.compose = compose, .blur = xrender_blur,
.fill = fill, .present = xrender_present,
.bind_pixmap = bind_pixmap, .bind_pixmap = xrender_bind_pixmap,
.release_image = release_image,
.create_shadow_context = default_create_shadow_context, .create_shadow_context = default_create_shadow_context,
.destroy_shadow_context = default_destroy_shadow_context, .destroy_shadow_context = default_destroy_shadow_context,
.render_shadow = default_render_shadow, .render_shadow = default_render_shadow,
.make_mask = make_mask, .make_mask = xrender_make_mask,
.release_image = xrender_release_image,
.is_image_transparent = default_is_image_transparent, .is_image_transparent = default_is_image_transparent,
.buffer_age = buffer_age, .buffer_age = xrender_buffer_age,
.max_buffer_age = 2, .max_buffer_age = 2,
.set_image_property = xrender_set_image_property,
.image_op = image_op, .image_op = xrender_image_op,
.clone_image = clone_image, .clone_image = xrender_clone_image,
.set_image_property = set_image_property, .create_blur_context = xrender_create_blur_context,
.create_blur_context = create_blur_context, .destroy_blur_context = xrender_destroy_blur_context,
.destroy_blur_context = destroy_blur_context, .get_blur_size = xrender_get_blur_size};
.get_blur_size = get_blur_size,
};
// vim: set noet sw=8 ts=8: // vim: set noet sw=8 ts=8: