wlr_scene: Fix damage tracking with non atomic opaque region configuration

We need to intersect the opaque region with the node size or else we'll
get damage tracking effects with compositors attempting to use
wlr_scene_buffer_set_opaque_region() along with resizing the buffer
at the same time in a certain order.

Consider this: I have a new buffer that I want to commit to my scene buffer
that is smaller than the old one. However, I still have the old opaque
region that is the size of the old larger buffer, so that means that
for the small moment between when we reconfigure the opaque region for the
new buffer the opaque region will be oversized. Scene logic will then
try to apply occluding optimizations outside of the node boundaries
causing damage artifacts.
This commit is contained in:
Alexander Orzechowski 2023-07-22 19:07:21 -04:00
parent 63f5851b6f
commit a32180afa7

View file

@ -232,6 +232,9 @@ static bool scene_nodes_in_box(struct wlr_scene_node *node, struct wlr_box *box,
static void scene_node_opaque_region(struct wlr_scene_node *node, int x, int y, static void scene_node_opaque_region(struct wlr_scene_node *node, int x, int y,
pixman_region32_t *opaque) { pixman_region32_t *opaque) {
int width, height;
scene_node_get_size(node, &width, &height);
if (node->type == WLR_SCENE_NODE_RECT) { if (node->type == WLR_SCENE_NODE_RECT) {
struct wlr_scene_rect *scene_rect = wlr_scene_rect_from_node(node); struct wlr_scene_rect *scene_rect = wlr_scene_rect_from_node(node);
if (scene_rect->color[3] != 1) { if (scene_rect->color[3] != 1) {
@ -250,13 +253,12 @@ static void scene_node_opaque_region(struct wlr_scene_node *node, int x, int y,
if (!buffer_is_opaque(scene_buffer->buffer)) { if (!buffer_is_opaque(scene_buffer->buffer)) {
pixman_region32_copy(opaque, &scene_buffer->opaque_region); pixman_region32_copy(opaque, &scene_buffer->opaque_region);
pixman_region32_intersect_rect(opaque, opaque, 0, 0, width, height);
pixman_region32_translate(opaque, x, y); pixman_region32_translate(opaque, x, y);
return; return;
} }
} }
int width, height;
scene_node_get_size(node, &width, &height);
pixman_region32_fini(opaque); pixman_region32_fini(opaque);
pixman_region32_init_rect(opaque, x, y, width, height); pixman_region32_init_rect(opaque, x, y, width, height);
} }