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:
parent
6caa76a281
commit
729ea6575a
1 changed files with 18 additions and 33 deletions
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue