[PATCH 4/5] drm/damage-helper: Do partial updates if framebuffer has not been changed

Thomas Zimmermann tzimmermann at suse.de
Tue Sep 20 13:56:18 UTC 2022


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 <tzimmermann at 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



More information about the dri-devel mailing list