blob: 8a490f8d517c8f0d9c32af8061f3423b0c321c56 [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"
28
29namespace android {
30
31template <class O>
32auto PipelineBindable<O>::BindPipeline(DrmDisplayPipeline *pipeline,
33 bool return_object_if_bound)
34 -> std::shared_ptr<BindingOwner<O>> {
35 auto owner_object = owner_object_.lock();
36 if (owner_object) {
37 if (bound_pipeline_ == pipeline && return_object_if_bound) {
38 return owner_object;
39 }
40
41 return {};
42 }
43 owner_object = std::make_shared<BindingOwner<O>>(static_cast<O *>(this));
44
45 bound_pipeline_ = pipeline;
46 return owner_object;
47}
48
49static auto TryCreatePipeline(DrmDevice &dev, DrmConnector &connector,
50 DrmEncoder &enc, DrmCrtc &crtc)
51 -> std::unique_ptr<DrmDisplayPipeline> {
52 /* Check if resources are available */
53
54 auto pipe = std::make_unique<DrmDisplayPipeline>();
55 pipe->device = &dev;
56
57 pipe->connector = connector.BindPipeline(pipe.get());
58 pipe->encoder = enc.BindPipeline(pipe.get());
59 pipe->crtc = crtc.BindPipeline(pipe.get());
60
61 if (!pipe->connector || !pipe->encoder || !pipe->crtc) {
62 return {};
63 }
64
65 std::vector<DrmPlane *> primary_planes;
66 std::vector<DrmPlane *> overlay_planes;
67
68 /* Attach necessary resources */
69 auto display_planes = std::vector<DrmPlane *>();
70 for (const auto &plane : dev.GetPlanes()) {
71 if (plane->IsCrtcSupported(crtc)) {
72 if (plane->GetType() == DRM_PLANE_TYPE_PRIMARY) {
73 primary_planes.emplace_back(plane.get());
74 } else if (plane->GetType() == DRM_PLANE_TYPE_OVERLAY) {
75 overlay_planes.emplace_back(plane.get());
76 } else {
77 ALOGI("Ignoring cursor plane %d", plane->GetId());
78 }
79 }
80 }
81
82 if (primary_planes.empty()) {
83 ALOGE("Primary plane for CRTC %d not found", crtc.GetId());
84 return {};
85 }
86
87 if (primary_planes.size() > 1) {
88 ALOGE("Found more than 1 primary plane for CRTC %d", crtc.GetId());
89 return {};
90 }
91
92 pipe->primary_plane = primary_planes[0]->BindPipeline(pipe.get());
93 if (!pipe->primary_plane) {
94 ALOGE("Primary plane %d is already owned. Internal error.",
95 primary_planes[0]->GetId());
96 return {};
97 }
98
99 bool use_overlay_planes = true; // TODO(rsglobal): restore
100 // strtol(use_overlay_planes_prop, nullptr,
101 // 10);
102 if (use_overlay_planes) {
103 for (auto *plane : overlay_planes) {
104 auto op = plane->BindPipeline(pipe.get());
105 if (op) {
106 pipe->overlay_planes.emplace_back(op);
107 }
108 }
109 }
110
111 return pipe;
112}
113
114static auto TryCreatePipelineUsingEncoder(DrmDevice &dev, DrmConnector &conn,
115 DrmEncoder &enc)
116 -> std::unique_ptr<DrmDisplayPipeline> {
117 /* First try to use the currently-bound crtc */
118 auto *crtc = dev.FindCrtcById(enc.GetCurrentCrtcId());
119 if (crtc != nullptr) {
120 auto pipeline = TryCreatePipeline(dev, conn, enc, *crtc);
121 if (pipeline) {
122 return pipeline;
123 }
124 }
125
126 /* Try to find a possible crtc which will work */
127 for (const auto &crtc : dev.GetCrtcs()) {
128 if (enc.SupportsCrtc(*crtc)) {
129 auto pipeline = TryCreatePipeline(dev, conn, enc, *crtc);
130 if (pipeline) {
131 return pipeline;
132 }
133 }
134 }
135
136 /* We can't use this encoder, but nothing went wrong, try another one */
137 return {};
138}
139
140auto DrmDisplayPipeline::CreatePipeline(DrmConnector &connector)
141 -> std::unique_ptr<DrmDisplayPipeline> {
142 auto &dev = connector.GetDev();
143 /* Try to use current setup first */
144 auto *encoder = dev.FindEncoderById(connector.GetCurrentEncoderId());
145
146 if (encoder != nullptr) {
147 auto pipeline = TryCreatePipelineUsingEncoder(dev, connector, *encoder);
148 if (pipeline) {
149 return pipeline;
150 }
151 }
152
153 for (const auto &enc : dev.GetEncoders()) {
154 if (connector.SupportsEncoder(*enc)) {
155 auto pipeline = TryCreatePipelineUsingEncoder(dev, connector, *enc);
156 if (pipeline) {
157 return pipeline;
158 }
159 }
160 }
161
162 ALOGE("Could not find a suitable encoder/crtc for connector %s",
163 connector.GetName().c_str());
164
165 return {};
166}
167
168} // namespace android