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 #pragma once 18 19 #include <pthread.h> 20 21 #include <memory> 22 #include <optional> 23 24 #include "compositor/DrmKmsPlan.h" 25 #include "compositor/LayerData.h" 26 #include "drm/DrmPlane.h" 27 #include "drm/ResourceManager.h" 28 #include "drm/VSyncWorker.h" 29 30 namespace android { 31 32 struct AtomicCommitArgs { 33 /* inputs. All fields are optional, but at least one has to be specified */ 34 bool test_only = false; 35 std::optional<DrmMode> display_mode; 36 std::optional<bool> active; 37 std::shared_ptr<DrmKmsPlan> composition; 38 std::shared_ptr<drm_color_ctm> color_matrix; 39 40 std::shared_ptr<DrmFbIdHandle> writeback_fb; 41 SharedFd writeback_release_fence; 42 43 /* out */ 44 SharedFd out_fence; 45 46 /* helpers */ 47 auto HasInputs() const -> bool { 48 return display_mode || active || composition; 49 } 50 }; 51 52 class DrmAtomicStateManager { 53 public: 54 static auto CreateInstance(DrmDisplayPipeline *pipe) 55 -> std::shared_ptr<DrmAtomicStateManager>; 56 57 ~DrmAtomicStateManager() = default; 58 59 auto ExecuteAtomicCommit(AtomicCommitArgs &args) -> int; 60 auto ActivateDisplayUsingDPMS() -> int; 61 StopThread()62 void StopThread() { 63 { 64 const std::unique_lock lock(mutex_); 65 exit_thread_ = true; 66 } 67 cv_.notify_all(); 68 } 69 70 private: 71 DrmAtomicStateManager() = default; 72 auto CommitFrame(AtomicCommitArgs &args) -> int; 73 74 struct KmsState { 75 /* Required to cleanup unused planes */ 76 std::vector<std::shared_ptr<BindingOwner<DrmPlane>>> used_planes; 77 /* We have to hold a reference to framebuffer while displaying it , 78 * otherwise picture will blink */ 79 std::vector<std::shared_ptr<DrmFbIdHandle>> used_framebuffers; 80 81 DrmModeUserPropertyBlobUnique mode_blob; 82 DrmModeUserPropertyBlobUnique ctm_blob; 83 84 int release_fence_pt_index{}; 85 86 /* To avoid setting the inactive state twice, which will fail the commit */ 87 bool crtc_active_state{}; 88 } active_frame_state_; 89 90 auto NewFrameState() -> KmsState { 91 auto *prev_frame_state = &active_frame_state_; 92 return (KmsState){ 93 .used_planes = prev_frame_state->used_planes, 94 .crtc_active_state = prev_frame_state->crtc_active_state, 95 }; 96 } 97 98 DrmDisplayPipeline *pipe_{}; 99 100 void CleanupPriorFrameResources(); 101 102 KmsState staged_frame_state_; 103 SharedFd last_present_fence_; 104 int frames_staged_{}; 105 int frames_tracked_{}; 106 107 void ThreadFn(const std::shared_ptr<DrmAtomicStateManager> &dasm); 108 std::condition_variable cv_; 109 std::mutex mutex_; 110 bool exit_thread_{}; 111 }; 112 113 } // namespace android 114