xref: /aosp_15_r20/external/drm_hwcomposer/drm/ResourceManager.cpp (revision 0a9764fe0a15e71ebbeb85e87e10990c23aab47f)
1*0a9764feSAndroid Build Coastguard Worker /*
2*0a9764feSAndroid Build Coastguard Worker  * Copyright (C) 2018 The Android Open Source Project
3*0a9764feSAndroid Build Coastguard Worker  *
4*0a9764feSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*0a9764feSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*0a9764feSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*0a9764feSAndroid Build Coastguard Worker  *
8*0a9764feSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*0a9764feSAndroid Build Coastguard Worker  *
10*0a9764feSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*0a9764feSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*0a9764feSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*0a9764feSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*0a9764feSAndroid Build Coastguard Worker  * limitations under the License.
15*0a9764feSAndroid Build Coastguard Worker  */
16*0a9764feSAndroid Build Coastguard Worker 
17*0a9764feSAndroid Build Coastguard Worker #define LOG_TAG "drmhwc"
18*0a9764feSAndroid Build Coastguard Worker 
19*0a9764feSAndroid Build Coastguard Worker #include "ResourceManager.h"
20*0a9764feSAndroid Build Coastguard Worker 
21*0a9764feSAndroid Build Coastguard Worker #include <sys/stat.h>
22*0a9764feSAndroid Build Coastguard Worker 
23*0a9764feSAndroid Build Coastguard Worker #include <ctime>
24*0a9764feSAndroid Build Coastguard Worker #include <sstream>
25*0a9764feSAndroid Build Coastguard Worker 
26*0a9764feSAndroid Build Coastguard Worker #include "bufferinfo/BufferInfoGetter.h"
27*0a9764feSAndroid Build Coastguard Worker #include "drm/DrmAtomicStateManager.h"
28*0a9764feSAndroid Build Coastguard Worker #include "drm/DrmDevice.h"
29*0a9764feSAndroid Build Coastguard Worker #include "drm/DrmDisplayPipeline.h"
30*0a9764feSAndroid Build Coastguard Worker #include "drm/DrmPlane.h"
31*0a9764feSAndroid Build Coastguard Worker #include "utils/log.h"
32*0a9764feSAndroid Build Coastguard Worker #include "utils/properties.h"
33*0a9764feSAndroid Build Coastguard Worker 
34*0a9764feSAndroid Build Coastguard Worker namespace android {
35*0a9764feSAndroid Build Coastguard Worker 
ResourceManager(PipelineToFrontendBindingInterface * p2f_bind_interface)36*0a9764feSAndroid Build Coastguard Worker ResourceManager::ResourceManager(
37*0a9764feSAndroid Build Coastguard Worker     PipelineToFrontendBindingInterface *p2f_bind_interface)
38*0a9764feSAndroid Build Coastguard Worker     : frontend_interface_(p2f_bind_interface) {
39*0a9764feSAndroid Build Coastguard Worker   uevent_listener_ = UEventListener::CreateInstance();
40*0a9764feSAndroid Build Coastguard Worker }
41*0a9764feSAndroid Build Coastguard Worker 
~ResourceManager()42*0a9764feSAndroid Build Coastguard Worker ResourceManager::~ResourceManager() {
43*0a9764feSAndroid Build Coastguard Worker   uevent_listener_->StopThread();
44*0a9764feSAndroid Build Coastguard Worker }
45*0a9764feSAndroid Build Coastguard Worker 
Init()46*0a9764feSAndroid Build Coastguard Worker void ResourceManager::Init() {
47*0a9764feSAndroid Build Coastguard Worker   if (initialized_) {
48*0a9764feSAndroid Build Coastguard Worker     ALOGE("Already initialized");
49*0a9764feSAndroid Build Coastguard Worker     return;
50*0a9764feSAndroid Build Coastguard Worker   }
51*0a9764feSAndroid Build Coastguard Worker 
52*0a9764feSAndroid Build Coastguard Worker   char path_pattern[PROPERTY_VALUE_MAX];
53*0a9764feSAndroid Build Coastguard Worker   // Could be a valid path or it can have at the end of it the wildcard %
54*0a9764feSAndroid Build Coastguard Worker   // which means that it will try open all devices until an error is met.
55*0a9764feSAndroid Build Coastguard Worker   auto path_len = property_get("vendor.hwc.drm.device", path_pattern,
56*0a9764feSAndroid Build Coastguard Worker                                "/dev/dri/card%");
57*0a9764feSAndroid Build Coastguard Worker   if (path_pattern[path_len - 1] != '%') {
58*0a9764feSAndroid Build Coastguard Worker     auto dev = DrmDevice::CreateInstance(path_pattern, this);
59*0a9764feSAndroid Build Coastguard Worker     if (dev) {
60*0a9764feSAndroid Build Coastguard Worker       drms_.emplace_back(std::move(dev));
61*0a9764feSAndroid Build Coastguard Worker     }
62*0a9764feSAndroid Build Coastguard Worker   } else {
63*0a9764feSAndroid Build Coastguard Worker     path_pattern[path_len - 1] = '\0';
64*0a9764feSAndroid Build Coastguard Worker     for (int idx = 0;; ++idx) {
65*0a9764feSAndroid Build Coastguard Worker       std::ostringstream path;
66*0a9764feSAndroid Build Coastguard Worker       path << path_pattern << idx;
67*0a9764feSAndroid Build Coastguard Worker 
68*0a9764feSAndroid Build Coastguard Worker       struct stat buf {};
69*0a9764feSAndroid Build Coastguard Worker       if (stat(path.str().c_str(), &buf) != 0)
70*0a9764feSAndroid Build Coastguard Worker         break;
71*0a9764feSAndroid Build Coastguard Worker 
72*0a9764feSAndroid Build Coastguard Worker       auto dev = DrmDevice::CreateInstance(path.str(), this);
73*0a9764feSAndroid Build Coastguard Worker       if (dev) {
74*0a9764feSAndroid Build Coastguard Worker         drms_.emplace_back(std::move(dev));
75*0a9764feSAndroid Build Coastguard Worker       }
76*0a9764feSAndroid Build Coastguard Worker     }
77*0a9764feSAndroid Build Coastguard Worker   }
78*0a9764feSAndroid Build Coastguard Worker 
79*0a9764feSAndroid Build Coastguard Worker   char proptext[PROPERTY_VALUE_MAX];
80*0a9764feSAndroid Build Coastguard Worker   property_get("vendor.hwc.drm.scale_with_gpu", proptext, "0");
81*0a9764feSAndroid Build Coastguard Worker   scale_with_gpu_ = bool(strncmp(proptext, "0", 1));
82*0a9764feSAndroid Build Coastguard Worker 
83*0a9764feSAndroid Build Coastguard Worker   constexpr char kDrmOrGpu[] = "DRM_OR_GPU";
84*0a9764feSAndroid Build Coastguard Worker   constexpr char kDrmOrIgnore[] = "DRM_OR_IGNORE";
85*0a9764feSAndroid Build Coastguard Worker   property_get("vendor.hwc.drm.ctm", proptext, kDrmOrGpu);
86*0a9764feSAndroid Build Coastguard Worker   if (strncmp(proptext, kDrmOrGpu, sizeof(kDrmOrGpu)) == 0) {
87*0a9764feSAndroid Build Coastguard Worker     ctm_handling_ = CtmHandling::kDrmOrGpu;
88*0a9764feSAndroid Build Coastguard Worker   } else if (strncmp(proptext, kDrmOrIgnore, sizeof(kDrmOrIgnore)) == 0) {
89*0a9764feSAndroid Build Coastguard Worker     ctm_handling_ = CtmHandling::kDrmOrIgnore;
90*0a9764feSAndroid Build Coastguard Worker   } else {
91*0a9764feSAndroid Build Coastguard Worker     ALOGE("Invalid value for vendor.hwc.drm.ctm: %s", proptext);
92*0a9764feSAndroid Build Coastguard Worker     ctm_handling_ = CtmHandling::kDrmOrGpu;
93*0a9764feSAndroid Build Coastguard Worker   }
94*0a9764feSAndroid Build Coastguard Worker 
95*0a9764feSAndroid Build Coastguard Worker   if (BufferInfoGetter::GetInstance() == nullptr) {
96*0a9764feSAndroid Build Coastguard Worker     ALOGE("Failed to initialize BufferInfoGetter");
97*0a9764feSAndroid Build Coastguard Worker     return;
98*0a9764feSAndroid Build Coastguard Worker   }
99*0a9764feSAndroid Build Coastguard Worker 
100*0a9764feSAndroid Build Coastguard Worker   uevent_listener_->RegisterHotplugHandler([this] {
101*0a9764feSAndroid Build Coastguard Worker     const std::unique_lock lock(GetMainLock());
102*0a9764feSAndroid Build Coastguard Worker     UpdateFrontendDisplays();
103*0a9764feSAndroid Build Coastguard Worker   });
104*0a9764feSAndroid Build Coastguard Worker 
105*0a9764feSAndroid Build Coastguard Worker   UpdateFrontendDisplays();
106*0a9764feSAndroid Build Coastguard Worker 
107*0a9764feSAndroid Build Coastguard Worker   initialized_ = true;
108*0a9764feSAndroid Build Coastguard Worker }
109*0a9764feSAndroid Build Coastguard Worker 
DeInit()110*0a9764feSAndroid Build Coastguard Worker void ResourceManager::DeInit() {
111*0a9764feSAndroid Build Coastguard Worker   if (!initialized_) {
112*0a9764feSAndroid Build Coastguard Worker     ALOGE("Not initialized");
113*0a9764feSAndroid Build Coastguard Worker     return;
114*0a9764feSAndroid Build Coastguard Worker   }
115*0a9764feSAndroid Build Coastguard Worker 
116*0a9764feSAndroid Build Coastguard Worker   uevent_listener_->RegisterHotplugHandler({});
117*0a9764feSAndroid Build Coastguard Worker 
118*0a9764feSAndroid Build Coastguard Worker   DetachAllFrontendDisplays();
119*0a9764feSAndroid Build Coastguard Worker   drms_.clear();
120*0a9764feSAndroid Build Coastguard Worker 
121*0a9764feSAndroid Build Coastguard Worker   initialized_ = false;
122*0a9764feSAndroid Build Coastguard Worker }
123*0a9764feSAndroid Build Coastguard Worker 
GetTimeMonotonicNs()124*0a9764feSAndroid Build Coastguard Worker auto ResourceManager::GetTimeMonotonicNs() -> int64_t {
125*0a9764feSAndroid Build Coastguard Worker   struct timespec ts {};
126*0a9764feSAndroid Build Coastguard Worker   clock_gettime(CLOCK_MONOTONIC, &ts);
127*0a9764feSAndroid Build Coastguard Worker   constexpr int64_t kNsInSec = 1000000000LL;
128*0a9764feSAndroid Build Coastguard Worker   return int64_t(ts.tv_sec) * kNsInSec + int64_t(ts.tv_nsec);
129*0a9764feSAndroid Build Coastguard Worker }
130*0a9764feSAndroid Build Coastguard Worker 
UpdateFrontendDisplays()131*0a9764feSAndroid Build Coastguard Worker void ResourceManager::UpdateFrontendDisplays() {
132*0a9764feSAndroid Build Coastguard Worker   auto ordered_connectors = GetOrderedConnectors();
133*0a9764feSAndroid Build Coastguard Worker 
134*0a9764feSAndroid Build Coastguard Worker   for (auto *conn : ordered_connectors) {
135*0a9764feSAndroid Build Coastguard Worker     conn->UpdateModes();
136*0a9764feSAndroid Build Coastguard Worker     auto connected = conn->IsConnected();
137*0a9764feSAndroid Build Coastguard Worker     auto attached = attached_pipelines_.count(conn) != 0;
138*0a9764feSAndroid Build Coastguard Worker 
139*0a9764feSAndroid Build Coastguard Worker     if (connected != attached) {
140*0a9764feSAndroid Build Coastguard Worker       ALOGI("%s connector %s", connected ? "Attaching" : "Detaching",
141*0a9764feSAndroid Build Coastguard Worker             conn->GetName().c_str());
142*0a9764feSAndroid Build Coastguard Worker 
143*0a9764feSAndroid Build Coastguard Worker       if (connected) {
144*0a9764feSAndroid Build Coastguard Worker         std::shared_ptr<DrmDisplayPipeline>
145*0a9764feSAndroid Build Coastguard Worker             pipeline = DrmDisplayPipeline::CreatePipeline(*conn);
146*0a9764feSAndroid Build Coastguard Worker 
147*0a9764feSAndroid Build Coastguard Worker         if (pipeline) {
148*0a9764feSAndroid Build Coastguard Worker           frontend_interface_->BindDisplay(pipeline);
149*0a9764feSAndroid Build Coastguard Worker           attached_pipelines_[conn] = std::move(pipeline);
150*0a9764feSAndroid Build Coastguard Worker         }
151*0a9764feSAndroid Build Coastguard Worker       } else {
152*0a9764feSAndroid Build Coastguard Worker         auto &pipeline = attached_pipelines_[conn];
153*0a9764feSAndroid Build Coastguard Worker         frontend_interface_->UnbindDisplay(pipeline);
154*0a9764feSAndroid Build Coastguard Worker         attached_pipelines_.erase(conn);
155*0a9764feSAndroid Build Coastguard Worker       }
156*0a9764feSAndroid Build Coastguard Worker     }
157*0a9764feSAndroid Build Coastguard Worker     if (connected) {
158*0a9764feSAndroid Build Coastguard Worker       if (!conn->IsLinkStatusGood())
159*0a9764feSAndroid Build Coastguard Worker         frontend_interface_->NotifyDisplayLinkStatus(attached_pipelines_[conn]);
160*0a9764feSAndroid Build Coastguard Worker     }
161*0a9764feSAndroid Build Coastguard Worker   }
162*0a9764feSAndroid Build Coastguard Worker   frontend_interface_->FinalizeDisplayBinding();
163*0a9764feSAndroid Build Coastguard Worker }
164*0a9764feSAndroid Build Coastguard Worker 
DetachAllFrontendDisplays()165*0a9764feSAndroid Build Coastguard Worker void ResourceManager::DetachAllFrontendDisplays() {
166*0a9764feSAndroid Build Coastguard Worker   for (auto &p : attached_pipelines_) {
167*0a9764feSAndroid Build Coastguard Worker     frontend_interface_->UnbindDisplay(p.second);
168*0a9764feSAndroid Build Coastguard Worker   }
169*0a9764feSAndroid Build Coastguard Worker   attached_pipelines_.clear();
170*0a9764feSAndroid Build Coastguard Worker   frontend_interface_->FinalizeDisplayBinding();
171*0a9764feSAndroid Build Coastguard Worker }
172*0a9764feSAndroid Build Coastguard Worker 
GetOrderedConnectors()173*0a9764feSAndroid Build Coastguard Worker auto ResourceManager::GetOrderedConnectors() -> std::vector<DrmConnector *> {
174*0a9764feSAndroid Build Coastguard Worker   /* Put internal displays first then external to
175*0a9764feSAndroid Build Coastguard Worker    * ensure Internal will take Primary slot
176*0a9764feSAndroid Build Coastguard Worker    */
177*0a9764feSAndroid Build Coastguard Worker 
178*0a9764feSAndroid Build Coastguard Worker   std::vector<DrmConnector *> ordered_connectors;
179*0a9764feSAndroid Build Coastguard Worker 
180*0a9764feSAndroid Build Coastguard Worker   for (auto &drm : drms_) {
181*0a9764feSAndroid Build Coastguard Worker     for (const auto &conn : drm->GetConnectors()) {
182*0a9764feSAndroid Build Coastguard Worker       if (conn->IsInternal()) {
183*0a9764feSAndroid Build Coastguard Worker         ordered_connectors.emplace_back(conn.get());
184*0a9764feSAndroid Build Coastguard Worker       }
185*0a9764feSAndroid Build Coastguard Worker     }
186*0a9764feSAndroid Build Coastguard Worker   }
187*0a9764feSAndroid Build Coastguard Worker 
188*0a9764feSAndroid Build Coastguard Worker   for (auto &drm : drms_) {
189*0a9764feSAndroid Build Coastguard Worker     for (const auto &conn : drm->GetConnectors()) {
190*0a9764feSAndroid Build Coastguard Worker       if (conn->IsExternal()) {
191*0a9764feSAndroid Build Coastguard Worker         ordered_connectors.emplace_back(conn.get());
192*0a9764feSAndroid Build Coastguard Worker       }
193*0a9764feSAndroid Build Coastguard Worker     }
194*0a9764feSAndroid Build Coastguard Worker   }
195*0a9764feSAndroid Build Coastguard Worker 
196*0a9764feSAndroid Build Coastguard Worker   return ordered_connectors;
197*0a9764feSAndroid Build Coastguard Worker }
198*0a9764feSAndroid Build Coastguard Worker 
GetVirtualDisplayPipeline()199*0a9764feSAndroid Build Coastguard Worker auto ResourceManager::GetVirtualDisplayPipeline()
200*0a9764feSAndroid Build Coastguard Worker     -> std::shared_ptr<DrmDisplayPipeline> {
201*0a9764feSAndroid Build Coastguard Worker   for (auto &drm : drms_) {
202*0a9764feSAndroid Build Coastguard Worker     for (const auto &conn : drm->GetWritebackConnectors()) {
203*0a9764feSAndroid Build Coastguard Worker       auto pipeline = DrmDisplayPipeline::CreatePipeline(*conn);
204*0a9764feSAndroid Build Coastguard Worker       if (!pipeline) {
205*0a9764feSAndroid Build Coastguard Worker         ALOGE("Failed to create pipeline for writeback connector %s",
206*0a9764feSAndroid Build Coastguard Worker               conn->GetName().c_str());
207*0a9764feSAndroid Build Coastguard Worker       }
208*0a9764feSAndroid Build Coastguard Worker       if (pipeline) {
209*0a9764feSAndroid Build Coastguard Worker         return pipeline;
210*0a9764feSAndroid Build Coastguard Worker       }
211*0a9764feSAndroid Build Coastguard Worker     }
212*0a9764feSAndroid Build Coastguard Worker   }
213*0a9764feSAndroid Build Coastguard Worker   return {};
214*0a9764feSAndroid Build Coastguard Worker }
215*0a9764feSAndroid Build Coastguard Worker 
GetWritebackConnectorsCount()216*0a9764feSAndroid Build Coastguard Worker auto ResourceManager::GetWritebackConnectorsCount() -> uint32_t {
217*0a9764feSAndroid Build Coastguard Worker   uint32_t count = 0;
218*0a9764feSAndroid Build Coastguard Worker   for (auto &drm : drms_) {
219*0a9764feSAndroid Build Coastguard Worker     count += drm->GetWritebackConnectors().size();
220*0a9764feSAndroid Build Coastguard Worker   }
221*0a9764feSAndroid Build Coastguard Worker   return count;
222*0a9764feSAndroid Build Coastguard Worker }
223*0a9764feSAndroid Build Coastguard Worker 
224*0a9764feSAndroid Build Coastguard Worker }  // namespace android
225