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@xxxxxxx> --- 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