Set partial updates on a plane if the framebuffer has not been changed
on an atomic commit. If such a plane has damage clips, the driver will
use them; otherwise the update is effectively empty. Planes that change
their framebuffer still perform a full update.

This heuristic optimizes the case of setting a new framebuffer on a
plane. This would trigger a full update of all other planes. With the
new optimization, only the changed plane performs an update.

The commit adds the flag fb_changed to struct plane_state. Besides
the damage-handling code, drivers can look at the flag to determine
if they need to commit a plane's framebuffer settings.

Signed-off-by: Thomas Zimmermann <tzimmerm...@suse.de>
---
 drivers/gpu/drm/drm_atomic_helper.c       |  3 +++
 drivers/gpu/drm/drm_atomic_state_helper.c |  1 +
 drivers/gpu/drm/drm_damage_helper.c       | 19 +++++++++++++++----
 include/drm/drm_plane.h                   |  6 ++++++
 4 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
index ee5fea48b5cb..f19405fbee14 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -99,6 +99,9 @@ drm_atomic_helper_plane_changed(struct drm_atomic_state 
*state,
 
                crtc_state->planes_changed = true;
        }
+
+       if (old_plane_state->fb != plane_state->fb)
+               plane_state->fb_changed = true;
 }
 
 static int handle_conflicting_encoders(struct drm_atomic_state *state,
diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c 
b/drivers/gpu/drm/drm_atomic_state_helper.c
index 85b13c221bd8..94818fd4dd8f 100644
--- a/drivers/gpu/drm/drm_atomic_state_helper.c
+++ b/drivers/gpu/drm/drm_atomic_state_helper.c
@@ -339,6 +339,7 @@ void __drm_atomic_helper_plane_duplicate_state(struct 
drm_plane *plane,
        state->commit = NULL;
        state->fb_damage_clips = NULL;
        state->fb_damage_partial_update = false;
+       state->fb_changed = false;
 }
 EXPORT_SYMBOL(__drm_atomic_helper_plane_duplicate_state);
 
diff --git a/drivers/gpu/drm/drm_damage_helper.c 
b/drivers/gpu/drm/drm_damage_helper.c
index a603a3563c03..f43abf02df5b 100644
--- a/drivers/gpu/drm/drm_damage_helper.c
+++ b/drivers/gpu/drm/drm_damage_helper.c
@@ -97,11 +97,22 @@ void drm_atomic_helper_check_plane_damage(struct 
drm_atomic_state *state,
                }
        }
 
-       /*
-        * Damage clips are a good indicator for partial updates.
-        */
-       if (new_plane_state->fb_damage_clips)
+       if (new_plane_state->fb_damage_clips) {
+               /*
+                * Damage clips are a good indicator for partial updates.
+                */
                partial_update = true;
+       } else if (!new_plane_state->fb_changed) {
+               /*
+                * Also set a partial update if the framebuffer did not
+                * change. Without damage clips set, this will effectively
+                * not update the plane. The exception is with full modeset
+                * operations, where we do full plane update even if the
+                * framebuffer did not change. We already handled this case
+                * earlier in the function.
+                */
+               partial_update = true;
+       }
 
 out:
        new_plane_state->fb_damage_partial_update = partial_update;
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
index 3ba91349d799..8c2d0a2eb760 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -229,6 +229,12 @@ struct drm_plane_state {
         */
        bool visible;
 
+       /**
+        * @fb_changed: @fb has been changed. Used by the atomic helpers and
+        * drivers to steer the atomic commit control flow.
+        */
+       bool fb_changed : 1;
+
        /**
         * @scaling_filter:
         *
-- 
2.37.3

Reply via email to