xref: /aosp_15_r20/external/drm_hwcomposer/drm/DrmDisplayPipeline.cpp (revision 0a9764fe0a15e71ebbeb85e87e10990c23aab47f)
1*0a9764feSAndroid Build Coastguard Worker /*
2*0a9764feSAndroid Build Coastguard Worker  * Copyright (C) 2022 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 "DrmDisplayPipeline.h"
20*0a9764feSAndroid Build Coastguard Worker 
21*0a9764feSAndroid Build Coastguard Worker #include "DrmAtomicStateManager.h"
22*0a9764feSAndroid Build Coastguard Worker #include "DrmConnector.h"
23*0a9764feSAndroid Build Coastguard Worker #include "DrmCrtc.h"
24*0a9764feSAndroid Build Coastguard Worker #include "DrmDevice.h"
25*0a9764feSAndroid Build Coastguard Worker #include "DrmEncoder.h"
26*0a9764feSAndroid Build Coastguard Worker #include "DrmPlane.h"
27*0a9764feSAndroid Build Coastguard Worker #include "utils/log.h"
28*0a9764feSAndroid Build Coastguard Worker #include "utils/properties.h"
29*0a9764feSAndroid Build Coastguard Worker 
30*0a9764feSAndroid Build Coastguard Worker namespace android {
31*0a9764feSAndroid Build Coastguard Worker 
32*0a9764feSAndroid Build Coastguard Worker template <class O>
BindPipeline(DrmDisplayPipeline * pipeline,bool return_object_if_bound)33*0a9764feSAndroid Build Coastguard Worker auto PipelineBindable<O>::BindPipeline(DrmDisplayPipeline *pipeline,
34*0a9764feSAndroid Build Coastguard Worker                                        bool return_object_if_bound)
35*0a9764feSAndroid Build Coastguard Worker     -> std::shared_ptr<BindingOwner<O>> {
36*0a9764feSAndroid Build Coastguard Worker   auto owner_object = owner_object_.lock();
37*0a9764feSAndroid Build Coastguard Worker   if (owner_object) {
38*0a9764feSAndroid Build Coastguard Worker     if (bound_pipeline_ == pipeline && return_object_if_bound) {
39*0a9764feSAndroid Build Coastguard Worker       return owner_object;
40*0a9764feSAndroid Build Coastguard Worker     }
41*0a9764feSAndroid Build Coastguard Worker 
42*0a9764feSAndroid Build Coastguard Worker     return {};
43*0a9764feSAndroid Build Coastguard Worker   }
44*0a9764feSAndroid Build Coastguard Worker   owner_object = std::make_shared<BindingOwner<O>>(static_cast<O *>(this));
45*0a9764feSAndroid Build Coastguard Worker 
46*0a9764feSAndroid Build Coastguard Worker   owner_object_ = owner_object;
47*0a9764feSAndroid Build Coastguard Worker   bound_pipeline_ = pipeline;
48*0a9764feSAndroid Build Coastguard Worker   return owner_object;
49*0a9764feSAndroid Build Coastguard Worker }
50*0a9764feSAndroid Build Coastguard Worker 
TryCreatePipeline(DrmDevice & dev,DrmConnector & connector,DrmEncoder & enc,DrmCrtc & crtc)51*0a9764feSAndroid Build Coastguard Worker static auto TryCreatePipeline(DrmDevice &dev, DrmConnector &connector,
52*0a9764feSAndroid Build Coastguard Worker                               DrmEncoder &enc, DrmCrtc &crtc)
53*0a9764feSAndroid Build Coastguard Worker     -> std::unique_ptr<DrmDisplayPipeline> {
54*0a9764feSAndroid Build Coastguard Worker   /* Check if resources are available */
55*0a9764feSAndroid Build Coastguard Worker 
56*0a9764feSAndroid Build Coastguard Worker   auto pipe = std::make_unique<DrmDisplayPipeline>();
57*0a9764feSAndroid Build Coastguard Worker   pipe->device = &dev;
58*0a9764feSAndroid Build Coastguard Worker 
59*0a9764feSAndroid Build Coastguard Worker   pipe->connector = connector.BindPipeline(pipe.get());
60*0a9764feSAndroid Build Coastguard Worker   pipe->encoder = enc.BindPipeline(pipe.get());
61*0a9764feSAndroid Build Coastguard Worker   pipe->crtc = crtc.BindPipeline(pipe.get());
62*0a9764feSAndroid Build Coastguard Worker 
63*0a9764feSAndroid Build Coastguard Worker   if (!pipe->connector || !pipe->encoder || !pipe->crtc) {
64*0a9764feSAndroid Build Coastguard Worker     return {};
65*0a9764feSAndroid Build Coastguard Worker   }
66*0a9764feSAndroid Build Coastguard Worker 
67*0a9764feSAndroid Build Coastguard Worker   std::vector<DrmPlane *> primary_planes;
68*0a9764feSAndroid Build Coastguard Worker   std::vector<DrmPlane *> overlay_planes;
69*0a9764feSAndroid Build Coastguard Worker 
70*0a9764feSAndroid Build Coastguard Worker   /* Attach necessary resources */
71*0a9764feSAndroid Build Coastguard Worker   auto display_planes = std::vector<DrmPlane *>();
72*0a9764feSAndroid Build Coastguard Worker   for (const auto &plane : dev.GetPlanes()) {
73*0a9764feSAndroid Build Coastguard Worker     if (plane->IsCrtcSupported(crtc)) {
74*0a9764feSAndroid Build Coastguard Worker       if (plane->GetType() == DRM_PLANE_TYPE_PRIMARY) {
75*0a9764feSAndroid Build Coastguard Worker         primary_planes.emplace_back(plane.get());
76*0a9764feSAndroid Build Coastguard Worker       } else if (plane->GetType() == DRM_PLANE_TYPE_OVERLAY) {
77*0a9764feSAndroid Build Coastguard Worker         overlay_planes.emplace_back(plane.get());
78*0a9764feSAndroid Build Coastguard Worker       } else {
79*0a9764feSAndroid Build Coastguard Worker         ALOGI("Ignoring cursor plane %d", plane->GetId());
80*0a9764feSAndroid Build Coastguard Worker       }
81*0a9764feSAndroid Build Coastguard Worker     }
82*0a9764feSAndroid Build Coastguard Worker   }
83*0a9764feSAndroid Build Coastguard Worker 
84*0a9764feSAndroid Build Coastguard Worker   if (primary_planes.empty()) {
85*0a9764feSAndroid Build Coastguard Worker     ALOGE("Primary plane for CRTC %d not found", crtc.GetId());
86*0a9764feSAndroid Build Coastguard Worker     return {};
87*0a9764feSAndroid Build Coastguard Worker   }
88*0a9764feSAndroid Build Coastguard Worker 
89*0a9764feSAndroid Build Coastguard Worker   for (const auto &plane : primary_planes) {
90*0a9764feSAndroid Build Coastguard Worker     pipe->primary_plane = plane->BindPipeline(pipe.get());
91*0a9764feSAndroid Build Coastguard Worker     if (pipe->primary_plane) {
92*0a9764feSAndroid Build Coastguard Worker       break;
93*0a9764feSAndroid Build Coastguard Worker     }
94*0a9764feSAndroid Build Coastguard Worker   }
95*0a9764feSAndroid Build Coastguard Worker 
96*0a9764feSAndroid Build Coastguard Worker   if (!pipe->primary_plane) {
97*0a9764feSAndroid Build Coastguard Worker     ALOGE("Failed to bind primary plane");
98*0a9764feSAndroid Build Coastguard Worker     return {};
99*0a9764feSAndroid Build Coastguard Worker   }
100*0a9764feSAndroid Build Coastguard Worker 
101*0a9764feSAndroid Build Coastguard Worker   pipe->atomic_state_manager = DrmAtomicStateManager::CreateInstance(
102*0a9764feSAndroid Build Coastguard Worker       pipe.get());
103*0a9764feSAndroid Build Coastguard Worker 
104*0a9764feSAndroid Build Coastguard Worker   return pipe;
105*0a9764feSAndroid Build Coastguard Worker }
106*0a9764feSAndroid Build Coastguard Worker 
TryCreatePipelineUsingEncoder(DrmDevice & dev,DrmConnector & conn,DrmEncoder & enc)107*0a9764feSAndroid Build Coastguard Worker static auto TryCreatePipelineUsingEncoder(DrmDevice &dev, DrmConnector &conn,
108*0a9764feSAndroid Build Coastguard Worker                                           DrmEncoder &enc)
109*0a9764feSAndroid Build Coastguard Worker     -> std::unique_ptr<DrmDisplayPipeline> {
110*0a9764feSAndroid Build Coastguard Worker   /* First try to use the currently-bound crtc */
111*0a9764feSAndroid Build Coastguard Worker   auto *crtc = dev.FindCrtcById(enc.GetCurrentCrtcId());
112*0a9764feSAndroid Build Coastguard Worker   if (crtc != nullptr) {
113*0a9764feSAndroid Build Coastguard Worker     auto pipeline = TryCreatePipeline(dev, conn, enc, *crtc);
114*0a9764feSAndroid Build Coastguard Worker     if (pipeline) {
115*0a9764feSAndroid Build Coastguard Worker       return pipeline;
116*0a9764feSAndroid Build Coastguard Worker     }
117*0a9764feSAndroid Build Coastguard Worker   }
118*0a9764feSAndroid Build Coastguard Worker 
119*0a9764feSAndroid Build Coastguard Worker   /* Try to find a possible crtc which will work */
120*0a9764feSAndroid Build Coastguard Worker   for (const auto &crtc : dev.GetCrtcs()) {
121*0a9764feSAndroid Build Coastguard Worker     if (enc.SupportsCrtc(*crtc)) {
122*0a9764feSAndroid Build Coastguard Worker       auto pipeline = TryCreatePipeline(dev, conn, enc, *crtc);
123*0a9764feSAndroid Build Coastguard Worker       if (pipeline) {
124*0a9764feSAndroid Build Coastguard Worker         return pipeline;
125*0a9764feSAndroid Build Coastguard Worker       }
126*0a9764feSAndroid Build Coastguard Worker     }
127*0a9764feSAndroid Build Coastguard Worker   }
128*0a9764feSAndroid Build Coastguard Worker 
129*0a9764feSAndroid Build Coastguard Worker   /* We can't use this encoder, but nothing went wrong, try another one */
130*0a9764feSAndroid Build Coastguard Worker   return {};
131*0a9764feSAndroid Build Coastguard Worker }
132*0a9764feSAndroid Build Coastguard Worker 
CreatePipeline(DrmConnector & connector)133*0a9764feSAndroid Build Coastguard Worker auto DrmDisplayPipeline::CreatePipeline(DrmConnector &connector)
134*0a9764feSAndroid Build Coastguard Worker     -> std::unique_ptr<DrmDisplayPipeline> {
135*0a9764feSAndroid Build Coastguard Worker   auto &dev = connector.GetDev();
136*0a9764feSAndroid Build Coastguard Worker   /* Try to use current setup first */
137*0a9764feSAndroid Build Coastguard Worker   auto *encoder = dev.FindEncoderById(connector.GetCurrentEncoderId());
138*0a9764feSAndroid Build Coastguard Worker 
139*0a9764feSAndroid Build Coastguard Worker   if (encoder != nullptr) {
140*0a9764feSAndroid Build Coastguard Worker     auto pipeline = TryCreatePipelineUsingEncoder(dev, connector, *encoder);
141*0a9764feSAndroid Build Coastguard Worker     if (pipeline) {
142*0a9764feSAndroid Build Coastguard Worker       return pipeline;
143*0a9764feSAndroid Build Coastguard Worker     }
144*0a9764feSAndroid Build Coastguard Worker   }
145*0a9764feSAndroid Build Coastguard Worker 
146*0a9764feSAndroid Build Coastguard Worker   for (const auto &enc : dev.GetEncoders()) {
147*0a9764feSAndroid Build Coastguard Worker     if (connector.SupportsEncoder(*enc)) {
148*0a9764feSAndroid Build Coastguard Worker       auto pipeline = TryCreatePipelineUsingEncoder(dev, connector, *enc);
149*0a9764feSAndroid Build Coastguard Worker       if (pipeline) {
150*0a9764feSAndroid Build Coastguard Worker         return pipeline;
151*0a9764feSAndroid Build Coastguard Worker       }
152*0a9764feSAndroid Build Coastguard Worker     }
153*0a9764feSAndroid Build Coastguard Worker   }
154*0a9764feSAndroid Build Coastguard Worker 
155*0a9764feSAndroid Build Coastguard Worker   ALOGE("Could not find a suitable encoder/crtc for connector %s",
156*0a9764feSAndroid Build Coastguard Worker         connector.GetName().c_str());
157*0a9764feSAndroid Build Coastguard Worker 
158*0a9764feSAndroid Build Coastguard Worker   return {};
159*0a9764feSAndroid Build Coastguard Worker }
160*0a9764feSAndroid Build Coastguard Worker 
ReadUseOverlayProperty()161*0a9764feSAndroid Build Coastguard Worker static bool ReadUseOverlayProperty() {
162*0a9764feSAndroid Build Coastguard Worker   char use_overlay_planes_prop[PROPERTY_VALUE_MAX];
163*0a9764feSAndroid Build Coastguard Worker   property_get("vendor.hwc.drm.use_overlay_planes", use_overlay_planes_prop,
164*0a9764feSAndroid Build Coastguard Worker                "1");
165*0a9764feSAndroid Build Coastguard Worker   constexpr int kStrtolBase = 10;
166*0a9764feSAndroid Build Coastguard Worker   return strtol(use_overlay_planes_prop, nullptr, kStrtolBase) != 0;
167*0a9764feSAndroid Build Coastguard Worker }
168*0a9764feSAndroid Build Coastguard Worker 
GetUsablePlanes()169*0a9764feSAndroid Build Coastguard Worker auto DrmDisplayPipeline::GetUsablePlanes()
170*0a9764feSAndroid Build Coastguard Worker     -> std::vector<std::shared_ptr<BindingOwner<DrmPlane>>> {
171*0a9764feSAndroid Build Coastguard Worker   std::vector<std::shared_ptr<BindingOwner<DrmPlane>>> planes;
172*0a9764feSAndroid Build Coastguard Worker   planes.emplace_back(primary_plane);
173*0a9764feSAndroid Build Coastguard Worker 
174*0a9764feSAndroid Build Coastguard Worker   const static bool kUseOverlayPlanes = ReadUseOverlayProperty();
175*0a9764feSAndroid Build Coastguard Worker 
176*0a9764feSAndroid Build Coastguard Worker   if (kUseOverlayPlanes) {
177*0a9764feSAndroid Build Coastguard Worker     for (const auto &plane : device->GetPlanes()) {
178*0a9764feSAndroid Build Coastguard Worker       if (plane->IsCrtcSupported(*crtc->Get())) {
179*0a9764feSAndroid Build Coastguard Worker         if (plane->GetType() == DRM_PLANE_TYPE_OVERLAY) {
180*0a9764feSAndroid Build Coastguard Worker           auto op = plane->BindPipeline(this, true);
181*0a9764feSAndroid Build Coastguard Worker           if (op) {
182*0a9764feSAndroid Build Coastguard Worker             planes.emplace_back(op);
183*0a9764feSAndroid Build Coastguard Worker           }
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 
189*0a9764feSAndroid Build Coastguard Worker   return planes;
190*0a9764feSAndroid Build Coastguard Worker }
191*0a9764feSAndroid Build Coastguard Worker 
~DrmDisplayPipeline()192*0a9764feSAndroid Build Coastguard Worker DrmDisplayPipeline::~DrmDisplayPipeline() {
193*0a9764feSAndroid Build Coastguard Worker   if (atomic_state_manager)
194*0a9764feSAndroid Build Coastguard Worker     atomic_state_manager->StopThread();
195*0a9764feSAndroid Build Coastguard Worker }
196*0a9764feSAndroid Build Coastguard Worker 
197*0a9764feSAndroid Build Coastguard Worker }  // namespace android
198