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:
parent
80d7c469d5
commit
c75973027a
2 changed files with 8 additions and 5 deletions
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue