1
0
Fork 0

drm_hwcomposer: Use most recently committed state

When preparing the properties for a commit, the state for the currently
active frame is used, rather than the last committed frame. This is
incorrect and could lead to a scenario such as:

- Frame N: commit enables plane 1
- Frame N+1: commit uses plane 1, 2, 3
- Frame N+2: if executed before staged_frame_state_ is moved to
    active_frame_state_, the new KmsState::used_framebuffers will be
    initialized to {1}
  - commit uses planes 1, 2
  - plane 3 is not disabled by the unused_planes code in CommitFrame

A similar problem exists for the KmsState::crtc_active_state.

To avoid this issue, always use the last committed state, regardless of
whether the previous frame has been presented or not.

Change-Id: I840b5b0ca3a3cf477882cacf6b1d5c0313ae80cf
This commit is contained in:
Drew Davenport 2025-06-10 00:18:24 +00:00
parent 80d7c469d5
commit c75973027a
2 changed files with 8 additions and 5 deletions

View file

@ -51,7 +51,11 @@ auto DrmAtomicStateManager::CommitFrame(AtomicCommitArgs &args) -> int {
// NOLINTNEXTLINE(misc-const-correctness)
ATRACE_CALL();
if (args.active && *args.active == active_frame_state_.crtc_active_state) {
// new_frame_state is initialized to the current frame state, so use it
// instead of active_frame_state_ or staged_frame_state_ to avoid races.
auto new_frame_state = NewFrameState();
if (args.active && *args.active == new_frame_state.crtc_active_state) {
/* Don't set the same state twice */
args.active.reset();
}
@ -61,13 +65,11 @@ auto DrmAtomicStateManager::CommitFrame(AtomicCommitArgs &args) -> int {
return 0;
}
if (!active_frame_state_.crtc_active_state) {
if (!new_frame_state.crtc_active_state) {
/* Force activate display */
args.active = true;
}
auto new_frame_state = NewFrameState();
auto *crtc = pipe_->crtc->Get();
auto pset = MakeDrmModeAtomicReqUnique();

View file

@ -108,7 +108,8 @@ class DrmAtomicStateManager {
};
KmsState NewFrameState() REQUIRES(main_mutex_) {
auto *prev_frame_state = &active_frame_state_;
auto *prev_frame_state = last_present_fence_ ? &staged_frame_state_
: &active_frame_state_;
return (KmsState){
.used_planes = prev_frame_state->used_planes,
.crtc_active_state = prev_frame_state->crtc_active_state,