1
0
Fork 0
mirror of https://github.com/yshui/picom.git synced 2024-11-25 14:06:08 -05:00

backend/xrender: be less clever with blur passes

We used to use the target picture as the render target for the last blur
pass, instead of an intermediate picture. This saves a Composite requests.

With this commit, all blur passes are rendered into intermediate
pictures. Then the final blur result is composited into the target. This
is less efficient, but since blur is *essentially* non-functionaly on
xrender (unless you use xf86-video-intel), we can't make it much worse.

This is a preparation for implementing our own accelerated blur on the
xrender backend.

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui 2024-10-11 19:48:49 +01:00
parent 6caa76a281
commit 729ea6575a
No known key found for this signature in database
GPG key ID: D3A4405BE6CC17F4

View file

@ -583,39 +583,26 @@ static bool xrender_blur(struct backend_base *base, ivec2 origin,
// For more than 1 pass, we do:
// source -(pass 1)-> tmp0 -(pass 2)-> tmp1 ...
// -(pass n-1)-> tmp0 or tmp1 -(pass n)-> target
// -(pass n)-> tmp0 or tmp1 -(composite)-> target
// For 1 pass, we do:
// (if source == target)
// source -(pass 1)-> tmp0 -(copy)-> target
// (if source != target)
// source -(pass 1)-> target
xcb_render_picture_t dst_pict = target == source ? tmp_picture[0] : target->pict;
// source -(pass 1)-> tmp0 -(composite)-> target
xcb_render_picture_t dst_pict = tmp_picture[0];
ivec2 src_origin = {.x = extent_resized->x1, .y = extent_resized->y1};
ivec2 dst_origin = {};
int npasses = bctx->x_blur_kernel_count;
if (source == target && npasses == 1) {
npasses = 2;
}
for (int i = 0; i < npasses; i++) {
// Copy from source picture to destination. The filter must
// be applied on source picture, to get the nearby pixels outside the
// window.
xcb_render_picture_t pass_mask_pict =
dst_pict == target->pict ? mask_pict : XCB_NONE;
const uint8_t op = dst_pict == target->pict ? XCB_RENDER_PICT_OP_OVER
: XCB_RENDER_PICT_OP_SRC;
if (i < bctx->x_blur_kernel_count) {
xcb_render_set_picture_filter(
c->c, src_pict, to_u16_checked(strlen(filter)), filter,
to_u32_checked(bctx->x_blur_kernel[i]->size),
bctx->x_blur_kernel[i]->kernel);
}
xcb_render_set_picture_filter(c->c, src_pict,
to_u16_checked(strlen(filter)), filter,
to_u32_checked(bctx->x_blur_kernel[i]->size),
bctx->x_blur_kernel[i]->kernel);
// clang-format off
xcb_render_composite(c->c, op, src_pict, pass_mask_pict, dst_pict,
xcb_render_composite(c->c, XCB_RENDER_PICT_OP_SRC, src_pict, XCB_NONE, dst_pict,
to_i16_checked(src_origin.x) , to_i16_checked(src_origin.y),
to_i16_checked(-mask_pict_origin.x) , to_i16_checked(-mask_pict_origin.y),
to_i16_checked(dst_origin.x) , to_i16_checked(dst_origin.y),
0 , 0 ,
0 , 0 ,
width_resized , height_resized);
// clang-format on
@ -625,19 +612,17 @@ static bool xrender_blur(struct backend_base *base, ivec2 origin,
auto next_tmp = src_pict == source->pict ? tmp_picture[1] : src_pict;
src_pict = dst_pict;
if (i + 1 == npasses - 1) {
// Intermediary to target
dst_pict = target->pict;
dst_origin = (ivec2){.x = origin.x + extent_resized->x1,
.y = origin.y + extent_resized->y1};
} else {
// Intermediary to intermediary
dst_pict = next_tmp;
dst_origin = (ivec2){.x = 0, .y = 0};
}
dst_pict = next_tmp;
src_origin = (ivec2){.x = 0, .y = 0};
}
// Finally, we composite the last pass to the target picture
xcb_render_composite(
c->c, XCB_RENDER_PICT_OP_OVER, src_pict, mask_pict, target->pict, 0, 0,
to_i16_checked(-mask_pict_origin.x), to_i16_checked(-mask_pict_origin.y),
to_i16_checked(origin.x + extent_resized->x1),
to_i16_checked(origin.y + extent_resized->y1), width_resized, height_resized);
if (mask_allocated) {
x_free_picture(c, mask_pict);
}