blob: 1a8ad5bb76076e78f94978d6909908b58241a6a8 [file] [log] [blame]
Roman Stratiienkocad8e0c2022-01-31 16:40:16 +02001/*
2 * Copyright (C) 2022 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#define LOG_TAG "hwc-drm-display-pipeline"
18
19#include "DrmDisplayPipeline.h"
20
Roman Stratiienko4e994052022-02-09 17:40:35 +020021#include "DrmAtomicStateManager.h"
Roman Stratiienkocad8e0c2022-01-31 16:40:16 +020022#include "DrmConnector.h"
23#include "DrmCrtc.h"
24#include "DrmDevice.h"
25#include "DrmEncoder.h"
26#include "DrmPlane.h"
Roman Stratiienkocad8e0c2022-01-31 16:40:16 +020027#include "utils/log.h"
Roman Stratiienko19c162f2022-02-01 09:35:08 +020028#include "utils/properties.h"
Roman Stratiienkocad8e0c2022-01-31 16:40:16 +020029
30namespace android {
31
32template <class O>
33auto PipelineBindable<O>::BindPipeline(DrmDisplayPipeline *pipeline,
34 bool return_object_if_bound)
35 -> std::shared_ptr<BindingOwner<O>> {
36 auto owner_object = owner_object_.lock();
37 if (owner_object) {
38 if (bound_pipeline_ == pipeline && return_object_if_bound) {
39 return owner_object;
40 }
41
42 return {};
43 }
44 owner_object = std::make_shared<BindingOwner<O>>(static_cast<O *>(this));
45
Roman Stratiienko33a71fa2022-02-02 12:53:14 +020046 owner_object_ = owner_object;
Roman Stratiienkocad8e0c2022-01-31 16:40:16 +020047 bound_pipeline_ = pipeline;
48 return owner_object;
49}
50
51static auto TryCreatePipeline(DrmDevice &dev, DrmConnector &connector,
52 DrmEncoder &enc, DrmCrtc &crtc)
53 -> std::unique_ptr<DrmDisplayPipeline> {
54 /* Check if resources are available */
55
56 auto pipe = std::make_unique<DrmDisplayPipeline>();
57 pipe->device = &dev;
58
59 pipe->connector = connector.BindPipeline(pipe.get());
60 pipe->encoder = enc.BindPipeline(pipe.get());
61 pipe->crtc = crtc.BindPipeline(pipe.get());
62
63 if (!pipe->connector || !pipe->encoder || !pipe->crtc) {
64 return {};
65 }
66
67 std::vector<DrmPlane *> primary_planes;
68 std::vector<DrmPlane *> overlay_planes;
69
70 /* Attach necessary resources */
71 auto display_planes = std::vector<DrmPlane *>();
72 for (const auto &plane : dev.GetPlanes()) {
73 if (plane->IsCrtcSupported(crtc)) {
74 if (plane->GetType() == DRM_PLANE_TYPE_PRIMARY) {
75 primary_planes.emplace_back(plane.get());
76 } else if (plane->GetType() == DRM_PLANE_TYPE_OVERLAY) {
77 overlay_planes.emplace_back(plane.get());
78 } else {
79 ALOGI("Ignoring cursor plane %d", plane->GetId());
80 }
81 }
82 }
83
84 if (primary_planes.empty()) {
85 ALOGE("Primary plane for CRTC %d not found", crtc.GetId());
86 return {};
87 }
88
Roman Stratiienkoce2ce752022-09-29 19:55:01 +030089 for (const auto &plane : primary_planes) {
90 pipe->primary_plane = plane->BindPipeline(pipe.get());
91 if (pipe->primary_plane) {
92 break;
93 }
Roman Stratiienkocad8e0c2022-01-31 16:40:16 +020094 }
95
Roman Stratiienkocad8e0c2022-01-31 16:40:16 +020096 if (!pipe->primary_plane) {
Roman Stratiienkoce2ce752022-09-29 19:55:01 +030097 ALOGE("Failed to bind primary plane");
Roman Stratiienkocad8e0c2022-01-31 16:40:16 +020098 return {};
99 }
100
Roman Stratiienkof818d4c2022-12-28 20:12:19 +0200101 pipe->atomic_state_manager = DrmAtomicStateManager::CreateInstance(
Roman Stratiienko4e994052022-02-09 17:40:35 +0200102 pipe.get());
Roman Stratiienko19c162f2022-02-01 09:35:08 +0200103
Roman Stratiienkocad8e0c2022-01-31 16:40:16 +0200104 return pipe;
105}
106
107static auto TryCreatePipelineUsingEncoder(DrmDevice &dev, DrmConnector &conn,
108 DrmEncoder &enc)
109 -> std::unique_ptr<DrmDisplayPipeline> {
110 /* First try to use the currently-bound crtc */
111 auto *crtc = dev.FindCrtcById(enc.GetCurrentCrtcId());
112 if (crtc != nullptr) {
113 auto pipeline = TryCreatePipeline(dev, conn, enc, *crtc);
114 if (pipeline) {
115 return pipeline;
116 }
117 }
118
119 /* Try to find a possible crtc which will work */
120 for (const auto &crtc : dev.GetCrtcs()) {
121 if (enc.SupportsCrtc(*crtc)) {
122 auto pipeline = TryCreatePipeline(dev, conn, enc, *crtc);
123 if (pipeline) {
124 return pipeline;
125 }
126 }
127 }
128
129 /* We can't use this encoder, but nothing went wrong, try another one */
130 return {};
131}
132
133auto DrmDisplayPipeline::CreatePipeline(DrmConnector &connector)
134 -> std::unique_ptr<DrmDisplayPipeline> {
135 auto &dev = connector.GetDev();
136 /* Try to use current setup first */
137 auto *encoder = dev.FindEncoderById(connector.GetCurrentEncoderId());
138
139 if (encoder != nullptr) {
140 auto pipeline = TryCreatePipelineUsingEncoder(dev, connector, *encoder);
141 if (pipeline) {
142 return pipeline;
143 }
144 }
145
146 for (const auto &enc : dev.GetEncoders()) {
147 if (connector.SupportsEncoder(*enc)) {
148 auto pipeline = TryCreatePipelineUsingEncoder(dev, connector, *enc);
149 if (pipeline) {
150 return pipeline;
151 }
152 }
153 }
154
155 ALOGE("Could not find a suitable encoder/crtc for connector %s",
156 connector.GetName().c_str());
157
158 return {};
159}
160
Roman Stratiienko9362cef2022-02-02 09:53:50 +0200161static bool ReadUseOverlayProperty() {
162 char use_overlay_planes_prop[PROPERTY_VALUE_MAX];
163 property_get("vendor.hwc.drm.use_overlay_planes", use_overlay_planes_prop,
164 "1");
165 constexpr int kStrtolBase = 10;
166 return strtol(use_overlay_planes_prop, nullptr, kStrtolBase) != 0;
167}
168
169auto DrmDisplayPipeline::GetUsablePlanes()
170 -> std::vector<std::shared_ptr<BindingOwner<DrmPlane>>> {
171 std::vector<std::shared_ptr<BindingOwner<DrmPlane>>> planes;
172 planes.emplace_back(primary_plane);
173
Roman Stratiienkoa7913de2022-10-20 13:18:57 +0300174 const static bool kUseOverlayPlanes = ReadUseOverlayProperty();
Roman Stratiienko9362cef2022-02-02 09:53:50 +0200175
Roman Stratiienkoa7913de2022-10-20 13:18:57 +0300176 if (kUseOverlayPlanes) {
Roman Stratiienko9362cef2022-02-02 09:53:50 +0200177 for (const auto &plane : device->GetPlanes()) {
178 if (plane->IsCrtcSupported(*crtc->Get())) {
179 if (plane->GetType() == DRM_PLANE_TYPE_OVERLAY) {
180 auto op = plane->BindPipeline(this, true);
181 if (op) {
182 planes.emplace_back(op);
183 }
184 }
185 }
186 }
187 }
188
189 return planes;
190}
191
Roman Stratiienkof818d4c2022-12-28 20:12:19 +0200192DrmDisplayPipeline::~DrmDisplayPipeline() {
193 if (atomic_state_manager)
194 atomic_state_manager->StopThread();
195}
196
Roman Stratiienkocad8e0c2022-01-31 16:40:16 +0200197} // namespace android