mirror of
https://github.com/yshui/picom.git
synced 2025-04-07 17:44:04 -04:00
region: fix region scaling
We claim region_scale_floor returns the largest integer region contained by the scaling result. But in fact what it's doing is taking the floor of each rectangle of the region separated, which leaves gaps between rectangles. This is not what we want. Just always take the ceil instead, hopefully the difference is small enough to be unnoticeable. Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
parent
5ec2c873df
commit
e068dc8a73
4 changed files with 27 additions and 37 deletions
|
@ -360,7 +360,7 @@ static bool xrender_blit(struct backend_base *base, ivec2 origin,
|
|||
scoped_region_t source_mask_region;
|
||||
pixman_region32_init(&source_mask_region);
|
||||
pixman_region32_copy(&source_mask_region, args->target_mask);
|
||||
region_scale_ceil(&source_mask_region, origin, inverse_scale);
|
||||
region_scale(&source_mask_region, origin, inverse_scale);
|
||||
x_set_picture_clip_region(
|
||||
xd->base.c, tmp_pict, to_i16_checked(-origin.x),
|
||||
to_i16_checked(-origin.y), &source_mask_region);
|
||||
|
|
52
src/region.h
52
src/region.h
|
@ -162,39 +162,29 @@ static inline void region_intersect(region_t *region, ivec2 origin, const region
|
|||
pixman_region32_translate(region, origin.x, origin.y);
|
||||
}
|
||||
|
||||
#define define_region_scale(suffix, lower_bound, upper_bound) \
|
||||
static inline void region_scale##suffix(region_t *region, ivec2 origin, vec2 scale) { \
|
||||
if (vec2_eq(scale, SCALE_IDENTITY)) { \
|
||||
return; \
|
||||
} \
|
||||
\
|
||||
int n; \
|
||||
region_t tmp = *region; \
|
||||
auto r = pixman_region32_rectangles(&tmp, &n); \
|
||||
for (int i = 0; i < n; i++) { \
|
||||
r[i].x1 = to_i32_saturated( \
|
||||
lower_bound((r[i].x1 - origin.x) * scale.x + origin.x)); \
|
||||
r[i].y1 = to_i32_saturated( \
|
||||
lower_bound((r[i].y1 - origin.y) * scale.y + origin.y)); \
|
||||
r[i].x2 = to_i32_saturated( \
|
||||
upper_bound((r[i].x2 - origin.x) * scale.x + origin.x)); \
|
||||
r[i].y2 = to_i32_saturated( \
|
||||
upper_bound((r[i].y2 - origin.y) * scale.y + origin.y)); \
|
||||
} \
|
||||
\
|
||||
/* Manipulating the rectangles could break assumptions made internally \
|
||||
* by pixman, so we recreate the region with the rectangles to let \
|
||||
* pixman fix them. */ \
|
||||
pixman_region32_init_rects(region, r, n); \
|
||||
pixman_region32_fini(&tmp); \
|
||||
/// Scale the `region` by `scale`. The origin of scaling is `origin`. Returns the smallest
|
||||
/// integer region that contains the result.
|
||||
static inline void region_scale(region_t *region, ivec2 origin, vec2 scale) {
|
||||
if (vec2_eq(scale, SCALE_IDENTITY)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/// Scale the `region` by `scale`. The origin of scaling is `origin`. Returns the largest integer
|
||||
/// region that is contained in the result.
|
||||
define_region_scale(_floor, ceil, floor);
|
||||
/// Scale the `region` by `scale`. The origin of scaling is `origin`. Returns the smallest integer
|
||||
/// region that contains the result.
|
||||
define_region_scale(_ceil, floor, ceil);
|
||||
int n;
|
||||
region_t tmp = *region;
|
||||
auto r = pixman_region32_rectangles(&tmp, &n);
|
||||
for (int i = 0; i < n; i++) {
|
||||
r[i].x1 = to_i32_saturated(floor((r[i].x1 - origin.x) * scale.x + origin.x));
|
||||
r[i].y1 = to_i32_saturated(floor((r[i].y1 - origin.y) * scale.y + origin.y));
|
||||
r[i].x2 = to_i32_saturated(ceil((r[i].x2 - origin.x) * scale.x + origin.x));
|
||||
r[i].y2 = to_i32_saturated(ceil((r[i].y2 - origin.y) * scale.y + origin.y));
|
||||
}
|
||||
|
||||
/* Manipulating the rectangles could break assumptions made internally
|
||||
* by pixman, so we recreate the region with the rectangles to let
|
||||
* pixman fix them. */
|
||||
pixman_region32_init_rects(region, r, n);
|
||||
pixman_region32_fini(&tmp);
|
||||
}
|
||||
|
||||
/// Calculate the symmetric difference of `region1`, and `region2`, and union the result
|
||||
/// into `result`. The two input regions has to be in the same coordinate space.
|
||||
|
|
|
@ -51,8 +51,8 @@ commands_for_window_body(struct layer *layer, struct backend_command *cmd,
|
|||
if (w->corner_radius > 0) {
|
||||
win_region_remove_corners(w, layer->window.origin, &cmd->opaque_region);
|
||||
}
|
||||
region_scale_floor(&cmd->target_mask, layer->window.origin, layer->scale);
|
||||
region_scale_floor(&cmd->opaque_region, layer->window.origin, layer->scale);
|
||||
region_scale(&cmd->target_mask, layer->window.origin, layer->scale);
|
||||
region_scale(&cmd->opaque_region, layer->window.origin, layer->scale);
|
||||
pixman_region32_intersect(&cmd->target_mask, &cmd->target_mask, &crop);
|
||||
pixman_region32_intersect(&cmd->opaque_region, &cmd->opaque_region, &crop);
|
||||
cmd->op = BACKEND_COMMAND_BLIT;
|
||||
|
@ -77,7 +77,7 @@ commands_for_window_body(struct layer *layer, struct backend_command *cmd,
|
|||
cmd -= 1;
|
||||
|
||||
pixman_region32_copy(&cmd->target_mask, frame_region);
|
||||
region_scale_floor(&cmd->target_mask, cmd->origin, layer->scale);
|
||||
region_scale(&cmd->target_mask, cmd->origin, layer->scale);
|
||||
pixman_region32_intersect(&cmd->target_mask, &cmd->target_mask, &crop);
|
||||
pixman_region32_init(&cmd->opaque_region);
|
||||
cmd->op = BACKEND_COMMAND_BLIT;
|
||||
|
@ -179,7 +179,7 @@ command_for_blur(struct layer *layer, struct backend_command *cmd,
|
|||
} else {
|
||||
return 0;
|
||||
}
|
||||
region_scale_floor(&cmd->target_mask, layer->window.origin, layer->scale);
|
||||
region_scale(&cmd->target_mask, layer->window.origin, layer->scale);
|
||||
|
||||
scoped_region_t crop = region_from_box(layer->crop);
|
||||
pixman_region32_intersect(&cmd->target_mask, &cmd->target_mask, &crop);
|
||||
|
|
|
@ -97,7 +97,7 @@ command_blit_damage(region_t *damage, region_t *scratch_region, struct backend_c
|
|||
if (cmd1->source == BACKEND_COMMAND_SOURCE_WINDOW) {
|
||||
layout_manager_collect_window_damage(lm, layer_index, buffer_age,
|
||||
scratch_region);
|
||||
region_scale_floor(scratch_region, cmd2->origin, cmd2->blit.scale);
|
||||
region_scale(scratch_region, cmd2->origin, cmd2->blit.scale);
|
||||
pixman_region32_intersect(scratch_region, scratch_region, &cmd1->target_mask);
|
||||
pixman_region32_intersect(scratch_region, scratch_region, &cmd2->target_mask);
|
||||
pixman_region32_union(damage, damage, scratch_region);
|
||||
|
|
Loading…
Add table
Reference in a new issue