new backends: blur interface update
To prepare for different blur methods, the blur interface of backends has been splitted into two parts. Now to use blur, a blur context must be created first; then, the blur method should be called with the blur context created. Updated the existing backends to the new interface. Also implemented handling of the new blur options. Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
@@ -59,14 +59,17 @@ typedef struct _xrender_data {
|
||||
/// Width and height of the target pixmap
|
||||
int target_width, target_height;
|
||||
|
||||
xcb_special_event_t *present_event;
|
||||
} xrender_data;
|
||||
|
||||
struct _xrender_blur_context {
|
||||
enum blur_method method;
|
||||
/// Blur kernels converted to X format
|
||||
struct x_convolution_kernel **x_blur_kernel;
|
||||
|
||||
/// Number of blur kernels
|
||||
int x_blur_kernel_count;
|
||||
|
||||
xcb_special_event_t *present_event;
|
||||
} xrender_data;
|
||||
};
|
||||
|
||||
struct _xrender_image_data {
|
||||
// Pixmap that the client window draws to,
|
||||
@@ -123,8 +126,13 @@ 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, const region_t *reg_blur,
|
||||
const region_t *reg_visible) {
|
||||
static bool blur(backend_t *backend_data, double opacity, void *ctx_,
|
||||
const region_t *reg_blur, const region_t *reg_visible) {
|
||||
struct _xrender_blur_context *bctx = ctx_;
|
||||
if (bctx->method == BLUR_METHOD_NONE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
struct _xrender_data *xd = (void *)backend_data;
|
||||
xcb_connection_t *c = xd->base.c;
|
||||
region_t reg_op;
|
||||
@@ -178,17 +186,17 @@ static bool blur(backend_t *backend_data, double opacity, const region_t *reg_bl
|
||||
// For 1 pass, we do
|
||||
// back -(pass 1)-> tmp0 -(copy)-> target_buffer
|
||||
int i;
|
||||
for (i = 0; i < xd->x_blur_kernel_count; i++) {
|
||||
for (i = 0; i < bctx->x_blur_kernel_count; i++) {
|
||||
// Copy from source picture to destination. The filter must
|
||||
// be applied on source picture, to get the nearby pixels outside the
|
||||
// window.
|
||||
// TODO cache converted blur_kerns
|
||||
xcb_render_set_picture_filter(c, src_pict, to_u16_checked(strlen(filter)),
|
||||
filter,
|
||||
to_u32_checked(xd->x_blur_kernel[i]->size),
|
||||
xd->x_blur_kernel[i]->kernel);
|
||||
to_u32_checked(bctx->x_blur_kernel[i]->size),
|
||||
bctx->x_blur_kernel[i]->kernel);
|
||||
|
||||
if (i < xd->x_blur_kernel_count - 1 || i == 0) {
|
||||
if (i < bctx->x_blur_kernel_count - 1 || i == 0) {
|
||||
// This is not the last pass, or this is the first pass
|
||||
xcb_render_composite(c, XCB_RENDER_PICT_OP_SRC, src_pict,
|
||||
XCB_NONE, dst_pict, src_x, src_y, 0, 0, 0, 0,
|
||||
@@ -273,10 +281,6 @@ static void deinit(backend_t *backend_data) {
|
||||
xcb_render_free_picture(xd->base.c, xd->back[i]);
|
||||
xcb_free_pixmap(xd->base.c, xd->back_pixmap[i]);
|
||||
}
|
||||
for (int i = 0; i < xd->x_blur_kernel_count; i++) {
|
||||
free(xd->x_blur_kernel[i]);
|
||||
}
|
||||
free(xd->x_blur_kernel);
|
||||
if (xd->present_event) {
|
||||
xcb_unregister_for_special_event(xd->base.c, xd->present_event);
|
||||
}
|
||||
@@ -468,6 +472,50 @@ static void *copy(backend_t *base, const void *image, const region_t *reg) {
|
||||
return new_img;
|
||||
}
|
||||
|
||||
void *create_blur_context(backend_t *base, enum blur_method method, void *args) {
|
||||
auto ret = cmalloc(struct _xrender_blur_context);
|
||||
if (!method || method >= BLUR_METHOD_INVALID) {
|
||||
ret->method = BLUR_METHOD_NONE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret->method = BLUR_METHOD_KERNEL;
|
||||
struct conv **kernels;
|
||||
int kernel_count;
|
||||
if (method == BLUR_METHOD_KERNEL) {
|
||||
kernels = ((struct kernel_blur_args *)args)->kernels;
|
||||
kernel_count = ((struct kernel_blur_args *)args)->kernel_count;
|
||||
} else {
|
||||
kernels = generate_blur_kernel(method, args, &kernel_count);
|
||||
}
|
||||
|
||||
ret->x_blur_kernel = ccalloc(kernel_count, struct x_convolution_kernel *);
|
||||
for (int i = 0; i < kernel_count; i++) {
|
||||
int center = kernels[i]->h * kernels[i]->w / 2;
|
||||
x_create_convolution_kernel(kernels[i], kernels[i]->data[center],
|
||||
&ret->x_blur_kernel[i]);
|
||||
}
|
||||
ret->x_blur_kernel_count = kernel_count;
|
||||
|
||||
if (method != BLUR_METHOD_KERNEL) {
|
||||
// Kernels generated by generate_blur_kernel, so we need to free them.
|
||||
for (int i = 0; i < kernel_count; i++) {
|
||||
free(kernels[i]);
|
||||
}
|
||||
free(kernels);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void destroy_blur_context(backend_t *base, void *ctx_) {
|
||||
struct _xrender_blur_context *ctx = ctx_;
|
||||
for (int i = 0; i < ctx->x_blur_kernel_count; i++) {
|
||||
free(ctx->x_blur_kernel[i]);
|
||||
}
|
||||
free(ctx->x_blur_kernel);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
backend_t *backend_xrender_init(session_t *ps) {
|
||||
auto xd = ccalloc(1, struct _xrender_data);
|
||||
init_backend_base(&xd->base, ps);
|
||||
@@ -550,15 +598,6 @@ backend_t *backend_xrender_init(session_t *ps) {
|
||||
xd->root_pict = x_create_picture_with_visual_and_pixmap(
|
||||
ps->c, ps->vis, root_pixmap, 0, NULL);
|
||||
}
|
||||
|
||||
xd->x_blur_kernel = ccalloc(ps->o.blur_kernel_count, struct x_convolution_kernel *);
|
||||
for (int i = 0; i < ps->o.blur_kernel_count; i++) {
|
||||
int center = ps->o.blur_kerns[i]->h * ps->o.blur_kerns[i]->w / 2;
|
||||
x_create_convolution_kernel(ps->o.blur_kerns[i],
|
||||
ps->o.blur_kerns[i]->data[center],
|
||||
&xd->x_blur_kernel[i]);
|
||||
}
|
||||
xd->x_blur_kernel_count = ps->o.blur_kernel_count;
|
||||
return &xd->base;
|
||||
err:
|
||||
deinit(&xd->base);
|
||||
@@ -583,6 +622,8 @@ struct backend_operations xrender_ops = {
|
||||
|
||||
.image_op = image_op,
|
||||
.copy = copy,
|
||||
.create_blur_context = create_blur_context,
|
||||
.destroy_blur_context = destroy_blur_context,
|
||||
};
|
||||
|
||||
// vim: set noet sw=8 ts=8:
|
||||
|
||||
Reference in New Issue
Block a user