From c2d2773df57750081b16d56da13b5015d752cbd7 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Sun, 16 Oct 2022 20:14:01 -0400 Subject: [PATCH] wlr_scene: Handle fractional scaling better Try to alleviate scaling inaccuracies by implementing a fudge factor. --- types/scene/wlr_scene.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index c5c301a72..69d6f4a3e 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -270,6 +270,14 @@ static uint32_t region_area(pixman_region32_t *region) { return area; } +static void scale_output_damage(pixman_region32_t *damage, float scale) { + wlr_region_scale(damage, damage, scale); + + if (floor(scale) != scale) { + wlr_region_expand(damage, damage, 1); + } +} + static void scene_damage_outputs(struct wlr_scene *scene, pixman_region32_t *damage) { if (!pixman_region32_not_empty(damage)) { return; @@ -282,8 +290,7 @@ static void scene_damage_outputs(struct wlr_scene *scene, pixman_region32_t *dam pixman_region32_copy(&output_damage, damage); pixman_region32_translate(&output_damage, -scene_output->x, -scene_output->y); - wlr_region_scale(&output_damage, &output_damage, - scene_output->output->scale); + scale_output_damage(&output_damage, scene_output->output->scale); if (wlr_damage_ring_add(&scene_output->damage_ring, &output_damage)) { wlr_output_schedule_frame(scene_output->output); } @@ -649,6 +656,11 @@ void wlr_scene_buffer_set_buffer_with_damage(struct wlr_scene_buffer *scene_buff pixman_region32_intersect(&output_damage, &output_damage, &cull_region); pixman_region32_fini(&cull_region); + // if we are using fractional scaling add a 1px margin. + if (floor(output_scale) != output_scale) { + wlr_region_expand(&output_damage, &output_damage, 1); + } + pixman_region32_translate(&output_damage, (lx - scene_output->x) * output_scale, (ly - scene_output->y) * output_scale); @@ -1055,7 +1067,7 @@ static void scene_node_render(struct wlr_scene_node *node, pixman_region32_init(&render_region); pixman_region32_copy(&render_region, &node->visible); pixman_region32_translate(&render_region, -scene_output->x, -scene_output->y); - wlr_region_scale(&render_region, &render_region, output->scale); + scale_output_damage(&render_region, output->scale); pixman_region32_intersect(&render_region, &render_region, damage); if (!pixman_region32_not_empty(&render_region)) { pixman_region32_fini(&render_region); @@ -1534,6 +1546,8 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { // scene nodes above. Those scene nodes will just render atop having us // never see the background. if (scene_output->scene->calculate_visibility) { + float output_scale = scene_output->output->scale; + for (int i = list_len - 1; i >= 0; i--) { struct wlr_scene_node *node = list_data[i]; int x, y; @@ -1550,10 +1564,18 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { pixman_region32_intersect(&opaque, &opaque, &node->visible); pixman_region32_translate(&opaque, -scene_output->x, -scene_output->y); - wlr_region_scale(&opaque, &opaque, scene_output->output->scale); + wlr_region_scale(&opaque, &opaque, output_scale); pixman_region32_subtract(&background, &background, &opaque); pixman_region32_fini(&opaque); } + + if (floor(output_scale) != output_scale) { + wlr_region_expand(&background, &background, 1); + + // reintersect with the damage because we never want to render + // outside of the damage region + pixman_region32_intersect(&background, &background, &damage); + } } int nrects;