blob: 0ce1afc8dd607985ccd1391588ade923653f31fc [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 char use_overlay_planes_prop[PROPERTY_VALUE_MAX];
102 property_get("vendor.hwc.drm.use_overlay_planes", use_overlay_planes_prop,
103 "1");
104 constexpr int kStrtolBase = 10;
105 bool use_overlay_planes = strtol(use_overlay_planes_prop, nullptr,
106 kStrtolBase) != 0;
107
Roman Stratiienkocad8e0c2022-01-31 16:40:16 +0200108 if (use_overlay_planes) {
109 for (auto *plane : overlay_planes) {
110 auto op = plane->BindPipeline(pipe.get());
111 if (op) {
112 pipe->overlay_planes.emplace_back(op);
113 }
114 }
115 }
116
Roman Stratiienko19c162f2022-02-01 09:35:08 +0200117 pipe->compositor = std::make_unique<DrmDisplayCompositor>(pipe.get());
118
Roman Stratiienkocad8e0c2022-01-31 16:40:16 +0200119 return pipe;
120}
121
122static auto TryCreatePipelineUsingEncoder(DrmDevice &dev, DrmConnector &conn,
123 DrmEncoder &enc)
124 -> std::unique_ptr<DrmDisplayPipeline> {
125 /* First try to use the currently-bound crtc */
126 auto *crtc = dev.FindCrtcById(enc.GetCurrentCrtcId());
127 if (crtc != nullptr) {
128 auto pipeline = TryCreatePipeline(dev, conn, enc, *crtc);
129 if (pipeline) {
130 return pipeline;
131 }
132 }
133
134 /* Try to find a possible crtc which will work */
135 for (const auto &crtc : dev.GetCrtcs()) {
136 if (enc.SupportsCrtc(*crtc)) {
137 auto pipeline = TryCreatePipeline(dev, conn, enc, *crtc);
138 if (pipeline) {
139 return pipeline;
140 }
141 }
142 }
143
144 /* We can't use this encoder, but nothing went wrong, try another one */
145 return {};
146}
147
148auto DrmDisplayPipeline::CreatePipeline(DrmConnector &connector)
149 -> std::unique_ptr<DrmDisplayPipeline> {
150 auto &dev = connector.GetDev();
151 /* Try to use current setup first */
152 auto *encoder = dev.FindEncoderById(connector.GetCurrentEncoderId());
153
154 if (encoder != nullptr) {
155 auto pipeline = TryCreatePipelineUsingEncoder(dev, connector, *encoder);
156 if (pipeline) {
157 return pipeline;
158 }
159 }
160
161 for (const auto &enc : dev.GetEncoders()) {
162 if (connector.SupportsEncoder(*enc)) {
163 auto pipeline = TryCreatePipelineUsingEncoder(dev, connector, *enc);
164 if (pipeline) {
165 return pipeline;
166 }
167 }
168 }
169
170 ALOGE("Could not find a suitable encoder/crtc for connector %s",
171 connector.GetName().c_str());
172
173 return {};
174}
175
176} // namespace android