blob: 31bc764a28ad7237d2e9e9cf2ce460376d2599a6 [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
21#include "DrmConnector.h"
22#include "DrmCrtc.h"
23#include "DrmDevice.h"
24#include "DrmEncoder.h"
25#include "DrmPlane.h"
26#include "compositor/DrmDisplayCompositor.h"
27#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
89 if (primary_planes.size() > 1) {
90 ALOGE("Found more than 1 primary plane for CRTC %d", crtc.GetId());
91 return {};
92 }
93
94 pipe->primary_plane = primary_planes[0]->BindPipeline(pipe.get());
95 if (!pipe->primary_plane) {
96 ALOGE("Primary plane %d is already owned. Internal error.",
97 primary_planes[0]->GetId());
98 return {};
99 }
100
Roman Stratiienko19c162f2022-02-01 09:35:08 +0200101 pipe->compositor = std::make_unique<DrmDisplayCompositor>(pipe.get());
102
Roman Stratiienkocad8e0c2022-01-31 16:40:16 +0200103 return pipe;
104}
105
106static auto TryCreatePipelineUsingEncoder(DrmDevice &dev, DrmConnector &conn,
107 DrmEncoder &enc)
108 -> std::unique_ptr<DrmDisplayPipeline> {
109 /* First try to use the currently-bound crtc */
110 auto *crtc = dev.FindCrtcById(enc.GetCurrentCrtcId());
111 if (crtc != nullptr) {
112 auto pipeline = TryCreatePipeline(dev, conn, enc, *crtc);
113 if (pipeline) {
114 return pipeline;
115 }
116 }
117
118 /* Try to find a possible crtc which will work */
119 for (const auto &crtc : dev.GetCrtcs()) {
120 if (enc.SupportsCrtc(*crtc)) {
121 auto pipeline = TryCreatePipeline(dev, conn, enc, *crtc);
122 if (pipeline) {
123 return pipeline;
124 }
125 }
126 }
127
128 /* We can't use this encoder, but nothing went wrong, try another one */
129 return {};
130}
131
132auto DrmDisplayPipeline::CreatePipeline(DrmConnector &connector)
133 -> std::unique_ptr<DrmDisplayPipeline> {
134 auto &dev = connector.GetDev();
135 /* Try to use current setup first */
136 auto *encoder = dev.FindEncoderById(connector.GetCurrentEncoderId());
137
138 if (encoder != nullptr) {
139 auto pipeline = TryCreatePipelineUsingEncoder(dev, connector, *encoder);
140 if (pipeline) {
141 return pipeline;
142 }
143 }
144
145 for (const auto &enc : dev.GetEncoders()) {
146 if (connector.SupportsEncoder(*enc)) {
147 auto pipeline = TryCreatePipelineUsingEncoder(dev, connector, *enc);
148 if (pipeline) {
149 return pipeline;
150 }
151 }
152 }
153
154 ALOGE("Could not find a suitable encoder/crtc for connector %s",
155 connector.GetName().c_str());
156
157 return {};
158}
159
Roman Stratiienko9362cef2022-02-02 09:53:50 +0200160static bool ReadUseOverlayProperty() {
161 char use_overlay_planes_prop[PROPERTY_VALUE_MAX];
162 property_get("vendor.hwc.drm.use_overlay_planes", use_overlay_planes_prop,
163 "1");
164 constexpr int kStrtolBase = 10;
165 return strtol(use_overlay_planes_prop, nullptr, kStrtolBase) != 0;
166}
167
168auto DrmDisplayPipeline::GetUsablePlanes()
169 -> std::vector<std::shared_ptr<BindingOwner<DrmPlane>>> {
170 std::vector<std::shared_ptr<BindingOwner<DrmPlane>>> planes;
171 planes.emplace_back(primary_plane);
172
173 static bool use_overlay_planes = ReadUseOverlayProperty();
174
175 if (use_overlay_planes) {
176 for (const auto &plane : device->GetPlanes()) {
177 if (plane->IsCrtcSupported(*crtc->Get())) {
178 if (plane->GetType() == DRM_PLANE_TYPE_OVERLAY) {
179 auto op = plane->BindPipeline(this, true);
180 if (op) {
181 planes.emplace_back(op);
182 }
183 }
184 }
185 }
186 }
187
188 return planes;
189}
190
Roman Stratiienkocad8e0c2022-01-31 16:40:16 +0200191} // namespace android