• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ANDROID_DRM_ATOMIC_STATE_MANAGER_H_
18 #define ANDROID_DRM_ATOMIC_STATE_MANAGER_H_
19 
20 #include <pthread.h>
21 
22 #include <functional>
23 #include <memory>
24 #include <optional>
25 #include <sstream>
26 #include <tuple>
27 
28 #include "compositor/DrmKmsPlan.h"
29 #include "compositor/LayerData.h"
30 #include "drm/DrmPlane.h"
31 #include "drm/ResourceManager.h"
32 #include "drm/VSyncWorker.h"
33 
34 namespace android {
35 
36 struct AtomicCommitArgs {
37   /* inputs. All fields are optional, but at least one has to be specified */
38   bool test_only = false;
39   std::optional<DrmMode> display_mode;
40   std::optional<bool> active;
41   std::shared_ptr<DrmKmsPlan> composition;
42 
43   /* out */
44   UniqueFd out_fence;
45 
46   /* helpers */
47   auto HasInputs() -> bool {
48     return display_mode || active || composition;
49   }
50 };
51 
52 class PresentTrackerThread {
53  public:
54   explicit PresentTrackerThread(DrmAtomicStateManager *st_man);
55 
56   ~PresentTrackerThread();
57 
Stop()58   void Stop() {
59     /* Exit thread by signalling that object is no longer valid */
60     st_man_ = nullptr;
61     Notify();
62     pt_.detach();
63   }
64 
Notify()65   void Notify() {
66     cv_.notify_all();
67   }
68 
69  private:
70   DrmAtomicStateManager *st_man_{};
71 
72   void PresentTrackerThreadFn();
73 
74   std::condition_variable cv_;
75   std::thread pt_;
76   std::mutex *mutex_;
77 };
78 
79 class DrmAtomicStateManager {
80   friend class PresentTrackerThread;
81 
82  public:
DrmAtomicStateManager(DrmDisplayPipeline * pipe)83   explicit DrmAtomicStateManager(DrmDisplayPipeline *pipe)
84       : pipe_(pipe),
85         ptt_(std::make_unique<PresentTrackerThread>(this).release()){};
86 
87   DrmAtomicStateManager(const DrmAtomicStateManager &) = delete;
~DrmAtomicStateManager()88   ~DrmAtomicStateManager() {
89     ptt_->Stop();
90   }
91 
92   auto ExecuteAtomicCommit(AtomicCommitArgs &args) -> int;
93   auto ActivateDisplayUsingDPMS() -> int;
94 
95  private:
96   auto CommitFrame(AtomicCommitArgs &args) -> int;
97 
98   struct KmsState {
99     /* Required to cleanup unused planes */
100     std::vector<std::shared_ptr<BindingOwner<DrmPlane>>> used_planes;
101     /* We have to hold a reference to framebuffer while displaying it ,
102      * otherwise picture will blink */
103     std::vector<std::shared_ptr<DrmFbIdHandle>> used_framebuffers;
104 
105     DrmModeUserPropertyBlobUnique mode_blob;
106 
107     int release_fence_pt_index{};
108 
109     /* To avoid setting the inactive state twice, which will fail the commit */
110     bool crtc_active_state{};
111   } active_frame_state_;
112 
113   auto NewFrameState() -> KmsState {
114     auto *prev_frame_state = &active_frame_state_;
115     return (KmsState){
116         .used_planes = prev_frame_state->used_planes,
117         .crtc_active_state = prev_frame_state->crtc_active_state,
118     };
119   }
120 
121   DrmDisplayPipeline *const pipe_;
122 
123   void CleanupPriorFrameResources();
124 
125   /* Present (swap) tracking */
126   PresentTrackerThread *ptt_;
127   KmsState staged_frame_state_;
128   UniqueFd last_present_fence_;
129   int frames_staged_{};
130   int frames_tracked_{};
131 };
132 
133 }  // namespace android
134 
135 #endif  // ANDROID_DRM_DISPLAY_COMPOSITOR_H_
136