diff --git a/metadata/workarounds.xml b/metadata/workarounds.xml index 5a4c1b95f..036c245f3 100644 --- a/metadata/workarounds.xml +++ b/metadata/workarounds.xml @@ -57,6 +57,10 @@ + diff --git a/src/view/wlr-surface-node.cpp b/src/view/wlr-surface-node.cpp index 26c757a41..731980964 100644 --- a/src/view/wlr-surface-node.cpp +++ b/src/view/wlr-surface-node.cpp @@ -234,6 +234,7 @@ class wf::scene::wlr_surface_node_t::wlr_surface_render_instance_t : public rend wf::output_t *visible_on; damage_callback push_damage; + wf::region_t last_visibility; wf::signal::connection_t on_surface_damage = [=] (node_damage_signal *data) @@ -249,7 +250,17 @@ class wf::scene::wlr_surface_node_t::wlr_surface_render_instance_t : public rend } } - push_damage(data->region); + static wf::option_wrapper_t use_opaque_optimizations{ + "workarounds/enable_opaque_region_damage_optimizations" + }; + + if (use_opaque_optimizations) + { + push_damage(data->region & last_visibility); + } else + { + push_damage(data->region); + } }; public: @@ -400,13 +411,23 @@ class wf::scene::wlr_surface_node_t::wlr_surface_render_instance_t : public rend { auto our_box = self->get_bounding_box(); on_frame_done.disconnect(); + last_visibility = visible & our_box; - if (!(visible & our_box).empty()) + static wf::option_wrapper_t use_opaque_optimizations{ + "workarounds/enable_opaque_region_damage_optimizations" + }; + + if (!last_visibility.empty()) { // We are visible on the given output => send wl_surface.frame on output frame, so that clients // can draw the next frame. output->connect(&on_frame_done); - // TODO: compute actually visible region and disable damage reporting for that region. + + if (use_opaque_optimizations && self->surface) + { + pixman_region32_subtract(visible.to_pixman(), visible.to_pixman(), + &self->surface->opaque_region); + } } } };