wlr_scene: Handle fractional scaling better

Try to alleviate scaling inaccuracies by implementing a fudge factor.
This commit is contained in:
Alexander Orzechowski 2022-10-16 20:14:01 -04:00 committed by Ronan Pigott
parent 6d90518c97
commit c2d2773df5

View file

@ -270,6 +270,14 @@ static uint32_t region_area(pixman_region32_t *region) {
return area; 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) { static void scene_damage_outputs(struct wlr_scene *scene, pixman_region32_t *damage) {
if (!pixman_region32_not_empty(damage)) { if (!pixman_region32_not_empty(damage)) {
return; 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_copy(&output_damage, damage);
pixman_region32_translate(&output_damage, pixman_region32_translate(&output_damage,
-scene_output->x, -scene_output->y); -scene_output->x, -scene_output->y);
wlr_region_scale(&output_damage, &output_damage, scale_output_damage(&output_damage, scene_output->output->scale);
scene_output->output->scale);
if (wlr_damage_ring_add(&scene_output->damage_ring, &output_damage)) { if (wlr_damage_ring_add(&scene_output->damage_ring, &output_damage)) {
wlr_output_schedule_frame(scene_output->output); 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_intersect(&output_damage, &output_damage, &cull_region);
pixman_region32_fini(&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, pixman_region32_translate(&output_damage,
(lx - scene_output->x) * output_scale, (lx - scene_output->x) * output_scale,
(ly - scene_output->y) * 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_init(&render_region);
pixman_region32_copy(&render_region, &node->visible); pixman_region32_copy(&render_region, &node->visible);
pixman_region32_translate(&render_region, -scene_output->x, -scene_output->y); 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); pixman_region32_intersect(&render_region, &render_region, damage);
if (!pixman_region32_not_empty(&render_region)) { if (!pixman_region32_not_empty(&render_region)) {
pixman_region32_fini(&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 // scene nodes above. Those scene nodes will just render atop having us
// never see the background. // never see the background.
if (scene_output->scene->calculate_visibility) { if (scene_output->scene->calculate_visibility) {
float output_scale = scene_output->output->scale;
for (int i = list_len - 1; i >= 0; i--) { for (int i = list_len - 1; i >= 0; i--) {
struct wlr_scene_node *node = list_data[i]; struct wlr_scene_node *node = list_data[i];
int x, y; 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_intersect(&opaque, &opaque, &node->visible);
pixman_region32_translate(&opaque, -scene_output->x, -scene_output->y); 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_subtract(&background, &background, &opaque);
pixman_region32_fini(&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; int nrects;