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