drm_hwcomposer: Add non-blocking commit support
This change fixes FPS drop on multidisplay devices.
Also in some cases it gives graphics pipeline more free time to draw
in advance.
Signed-off-by: Roman Stratiienko <roman.o.stratiienko@globallogic.com>
diff --git a/drm/DrmAtomicStateManager.h b/drm/DrmAtomicStateManager.h
index 08a1c13..a50a214 100644
--- a/drm/DrmAtomicStateManager.h
+++ b/drm/DrmAtomicStateManager.h
@@ -49,11 +49,45 @@
}
};
-class DrmAtomicStateManager {
+class PresentTrackerThread {
public:
- explicit DrmAtomicStateManager(DrmDisplayPipeline *pipe) : pipe_(pipe){};
+ explicit PresentTrackerThread(DrmAtomicStateManager *st_man);
+
+ ~PresentTrackerThread();
+
+ void Stop() {
+ /* Exit thread by signalling that object is no longer valid */
+ st_man_ = nullptr;
+ Notify();
+ pt_.detach();
+ }
+
+ void Notify() {
+ cv_.notify_all();
+ }
+
+ private:
+ DrmAtomicStateManager *st_man_{};
+
+ void PresentTrackerThreadFn();
+
+ std::condition_variable cv_;
+ std::thread pt_;
+ std::mutex *mutex_;
+};
+
+class DrmAtomicStateManager {
+ friend class PresentTrackerThread;
+
+ public:
+ explicit DrmAtomicStateManager(DrmDisplayPipeline *pipe)
+ : pipe_(pipe),
+ ptt_(std::make_unique<PresentTrackerThread>(this).release()){};
+
DrmAtomicStateManager(const DrmAtomicStateManager &) = delete;
- ~DrmAtomicStateManager() = default;
+ ~DrmAtomicStateManager() {
+ ptt_->Stop();
+ }
auto ExecuteAtomicCommit(AtomicCommitArgs &args) -> int;
auto ActivateDisplayUsingDPMS() -> int;
@@ -70,20 +104,32 @@
DrmModeUserPropertyBlobUnique mode_blob;
+ int release_fence_pt_index{};
+
/* To avoid setting the inactive state twice, which will fail the commit */
bool crtc_active_state{};
} active_frame_state_;
auto NewFrameState() -> KmsState {
+ auto *prev_frame_state = &active_frame_state_;
return (KmsState){
- .used_planes = active_frame_state_.used_planes,
- .used_framebuffers = active_frame_state_.used_framebuffers,
- .crtc_active_state = active_frame_state_.crtc_active_state,
+ .used_planes = prev_frame_state->used_planes,
+ .crtc_active_state = prev_frame_state->crtc_active_state,
};
}
DrmDisplayPipeline *const pipe_;
+
+ void CleanupPriorFrameResources();
+
+ /* Present (swap) tracking */
+ PresentTrackerThread *ptt_;
+ KmsState staged_frame_state_;
+ UniqueFd last_present_fence_;
+ int frames_staged_{};
+ int frames_tracked_{};
};
+
} // namespace android
#endif // ANDROID_DRM_DISPLAY_COMPOSITOR_H_