blob: 30bf7408db3378d4bd001502acd0d36f51dd8ab0 [file] [log] [blame]
Roman Stratiienko3627beb2022-01-04 16:02:55 +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
Sean Paul468a7542024-07-16 19:50:58 +000017#define LOG_TAG "drmhwc"
Roman Stratiienko3627beb2022-01-04 16:02:55 +020018#define ATRACE_TAG ATRACE_TAG_GRAPHICS
19
20#include "HwcDisplay.h"
21
Roman Stratiienkobb594ba2022-02-18 16:52:03 +020022#include "backend/Backend.h"
Roman Stratiienko3627beb2022-01-04 16:02:55 +020023#include "backend/BackendManager.h"
24#include "bufferinfo/BufferInfoGetter.h"
Drew Davenport93443182023-12-14 09:25:45 +000025#include "drm/DrmHwc.h"
Roman Stratiienko3627beb2022-01-04 16:02:55 +020026#include "utils/log.h"
27#include "utils/properties.h"
28
29namespace android {
30
31std::string HwcDisplay::DumpDelta(HwcDisplay::Stats delta) {
32 if (delta.total_pixops_ == 0)
33 return "No stats yet";
Roman Stratiienkoa7913de2022-10-20 13:18:57 +030034 auto ratio = 1.0 - double(delta.gpu_pixops_) / double(delta.total_pixops_);
Roman Stratiienko3627beb2022-01-04 16:02:55 +020035
36 std::stringstream ss;
37 ss << " Total frames count: " << delta.total_frames_ << "\n"
38 << " Failed to test commit frames: " << delta.failed_kms_validate_ << "\n"
39 << " Failed to commit frames: " << delta.failed_kms_present_ << "\n"
40 << ((delta.failed_kms_present_ > 0)
41 ? " !!! Internal failure, FIX it please\n"
42 : "")
43 << " Flattened frames: " << delta.frames_flattened_ << "\n"
44 << " Pixel operations (free units)"
45 << " : [TOTAL: " << delta.total_pixops_ << " / GPU: " << delta.gpu_pixops_
46 << "]\n"
47 << " Composition efficiency: " << ratio;
48
49 return ss.str();
50}
51
52std::string HwcDisplay::Dump() {
Roman Stratiienkoa7913de2022-10-20 13:18:57 +030053 auto connector_name = IsInHeadlessMode()
54 ? std::string("NULL-DISPLAY")
55 : GetPipe().connector->Get()->GetName();
Roman Stratiienko19c162f2022-02-01 09:35:08 +020056
Roman Stratiienko3627beb2022-01-04 16:02:55 +020057 std::stringstream ss;
Roman Stratiienko19c162f2022-02-01 09:35:08 +020058 ss << "- Display on: " << connector_name << "\n"
Roman Stratiienko3627beb2022-01-04 16:02:55 +020059 << "Statistics since system boot:\n"
60 << DumpDelta(total_stats_) << "\n\n"
61 << "Statistics since last dumpsys request:\n"
62 << DumpDelta(total_stats_.minus(prev_stats_)) << "\n\n";
63
64 memcpy(&prev_stats_, &total_stats_, sizeof(Stats));
65 return ss.str();
66}
67
Roman Stratiienkobb594ba2022-02-18 16:52:03 +020068HwcDisplay::HwcDisplay(hwc2_display_t handle, HWC2::DisplayType type,
Drew Davenport93443182023-12-14 09:25:45 +000069 DrmHwc *hwc)
70 : hwc_(hwc), handle_(handle), type_(type), client_layer_(this) {
Roman Stratiienkof2c060f2023-09-18 22:46:08 +030071 if (type_ == HWC2::DisplayType::Virtual) {
72 writeback_layer_ = std::make_unique<HwcLayer>(this);
73 }
74}
Roman Stratiienko0da91bf2023-01-17 18:06:04 +020075
76void HwcDisplay::SetColorMarixToIdentity() {
77 color_matrix_ = std::make_shared<drm_color_ctm>();
78 for (int i = 0; i < kCtmCols; i++) {
79 for (int j = 0; j < kCtmRows; j++) {
Yongqin Liu152bc622023-01-29 00:48:10 +080080 constexpr uint64_t kOne = (1ULL << 32); /* 1.0 in s31.32 format */
Roman Stratiienko0da91bf2023-01-17 18:06:04 +020081 color_matrix_->matrix[i * kCtmRows + j] = (i == j) ? kOne : 0;
82 }
83 }
84
85 color_transform_hint_ = HAL_COLOR_TRANSFORM_IDENTITY;
Roman Stratiienko3dacd472022-01-11 19:18:34 +020086}
87
Roman Stratiienkobb594ba2022-02-18 16:52:03 +020088HwcDisplay::~HwcDisplay() = default;
Roman Stratiienko3dacd472022-01-11 19:18:34 +020089
Roman Stratiienko63762a92023-09-18 22:33:45 +030090void HwcDisplay::SetPipeline(std::shared_ptr<DrmDisplayPipeline> pipeline) {
Roman Stratiienkod0494d92022-03-15 18:02:04 +020091 Deinit();
92
Roman Stratiienko63762a92023-09-18 22:33:45 +030093 pipeline_ = std::move(pipeline);
Roman Stratiienkobb594ba2022-02-18 16:52:03 +020094
Roman Stratiienko63762a92023-09-18 22:33:45 +030095 if (pipeline_ != nullptr || handle_ == kPrimaryDisplay) {
Roman Stratiienkobb594ba2022-02-18 16:52:03 +020096 Init();
Drew Davenport93443182023-12-14 09:25:45 +000097 hwc_->ScheduleHotplugEvent(handle_, /*connected = */ true);
Roman Stratiienkobb594ba2022-02-18 16:52:03 +020098 } else {
Drew Davenport93443182023-12-14 09:25:45 +000099 hwc_->ScheduleHotplugEvent(handle_, /*connected = */ false);
Roman Stratiienkobb594ba2022-02-18 16:52:03 +0200100 }
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200101}
102
Roman Stratiienkod0494d92022-03-15 18:02:04 +0200103void HwcDisplay::Deinit() {
104 if (pipeline_ != nullptr) {
105 AtomicCommitArgs a_args{};
Roman Stratiienkod0494d92022-03-15 18:02:04 +0200106 a_args.composition = std::make_shared<DrmKmsPlan>();
107 GetPipe().atomic_state_manager->ExecuteAtomicCommit(a_args);
John Stultz799e8c72022-06-30 19:49:42 +0000108/*
109 * TODO:
110 * Unfortunately the following causes regressions on db845c
111 * with VtsHalGraphicsComposerV2_3TargetTest due to the display
112 * never coming back. Patches to avoiding that issue on the
113 * the kernel side unfortunately causes further crashes in
114 * drm_hwcomposer, because the client detach takes longer then the
115 * 1 second max VTS expects. So for now as a workaround, lets skip
116 * deactivating the display on deinit, which matches previous
117 * behavior prior to commit d0494d9b8097
118 */
119#if 0
Roman Stratiienkoaf862a52022-06-22 12:14:22 +0300120 a_args.composition = {};
121 a_args.active = false;
122 GetPipe().atomic_state_manager->ExecuteAtomicCommit(a_args);
John Stultz799e8c72022-06-30 19:49:42 +0000123#endif
Roman Stratiienkod0494d92022-03-15 18:02:04 +0200124
Roman Stratiienkod0494d92022-03-15 18:02:04 +0200125 current_plan_.reset();
126 backend_.reset();
Roman Stratiienko22fe9612023-01-17 21:22:29 +0200127 if (flatcon_) {
128 flatcon_->StopThread();
129 flatcon_.reset();
130 }
Roman Stratiienkod0494d92022-03-15 18:02:04 +0200131 }
132
Roman Stratiienkod2cc7382022-12-28 18:51:59 +0200133 if (vsync_worker_) {
134 vsync_worker_->StopThread();
135 vsync_worker_ = {};
136 }
137
Roman Stratiienkod0494d92022-03-15 18:02:04 +0200138 SetClientTarget(nullptr, -1, 0, {});
139}
140
Roman Stratiienko19c162f2022-02-01 09:35:08 +0200141HWC2::Error HwcDisplay::Init() {
Roman Stratiienkod0494d92022-03-15 18:02:04 +0200142 ChosePreferredConfig();
143
Roman Stratiienkod2cc7382022-12-28 18:51:59 +0200144 auto vsw_callbacks = (VSyncWorkerCallbacks){
145 .out_event =
146 [this](int64_t timestamp) {
Drew Davenport93443182023-12-14 09:25:45 +0000147 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
Roman Stratiienkod2cc7382022-12-28 18:51:59 +0200148 if (vsync_event_en_) {
149 uint32_t period_ns{};
150 GetDisplayVsyncPeriod(&period_ns);
Drew Davenport93443182023-12-14 09:25:45 +0000151 hwc_->SendVsyncEventToClient(handle_, timestamp, period_ns);
Roman Stratiienkod2cc7382022-12-28 18:51:59 +0200152 }
Roman Stratiienkod2cc7382022-12-28 18:51:59 +0200153 if (vsync_tracking_en_) {
154 last_vsync_ts_ = timestamp;
155 }
Roman Stratiienko22fe9612023-01-17 21:22:29 +0200156 if (!vsync_event_en_ && !vsync_tracking_en_) {
Roman Stratiienkod2cc7382022-12-28 18:51:59 +0200157 vsync_worker_->VSyncControl(false);
158 }
159 },
160 .get_vperiod_ns = [this]() -> uint32_t {
161 uint32_t outVsyncPeriod = 0;
162 GetDisplayVsyncPeriod(&outVsyncPeriod);
163 return outVsyncPeriod;
164 },
165 };
166
Roman Stratiienkof2c060f2023-09-18 22:46:08 +0300167 if (type_ != HWC2::DisplayType::Virtual) {
168 vsync_worker_ = VSyncWorker::CreateInstance(pipeline_, vsw_callbacks);
169 if (!vsync_worker_) {
170 ALOGE("Failed to create event worker for d=%d\n", int(handle_));
171 return HWC2::Error::BadDisplay;
172 }
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200173 }
174
Roman Stratiienko3dacd472022-01-11 19:18:34 +0200175 if (!IsInHeadlessMode()) {
Roman Stratiienkod2cc7382022-12-28 18:51:59 +0200176 auto ret = BackendManager::GetInstance().SetBackendForDisplay(this);
Roman Stratiienko3dacd472022-01-11 19:18:34 +0200177 if (ret) {
178 ALOGE("Failed to set backend for d=%d %d\n", int(handle_), ret);
179 return HWC2::Error::BadDisplay;
180 }
Drew Davenport93443182023-12-14 09:25:45 +0000181 auto flatcbk = (struct FlatConCallbacks){
182 .trigger = [this]() { hwc_->SendRefreshEventToClient(handle_); }};
Roman Stratiienko22fe9612023-01-17 21:22:29 +0200183 flatcon_ = FlatteningController::CreateInstance(flatcbk);
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200184 }
185
186 client_layer_.SetLayerBlendMode(HWC2_BLEND_MODE_PREMULTIPLIED);
187
Roman Stratiienko0da91bf2023-01-17 18:06:04 +0200188 SetColorMarixToIdentity();
189
Roman Stratiienko3dacd472022-01-11 19:18:34 +0200190 return HWC2::Error::None;
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200191}
192
193HWC2::Error HwcDisplay::ChosePreferredConfig() {
Roman Stratiienko3dacd472022-01-11 19:18:34 +0200194 HWC2::Error err{};
Roman Stratiienkof2c060f2023-09-18 22:46:08 +0300195 if (type_ == HWC2::DisplayType::Virtual) {
196 configs_.GenFakeMode(virtual_disp_width_, virtual_disp_height_);
197 } else if (!IsInHeadlessMode()) {
Roman Stratiienko3dacd472022-01-11 19:18:34 +0200198 err = configs_.Update(*pipeline_->connector->Get());
199 } else {
Roman Stratiienkof2c060f2023-09-18 22:46:08 +0300200 configs_.GenFakeMode(0, 0);
Roman Stratiienko3dacd472022-01-11 19:18:34 +0200201 }
202 if (!IsInHeadlessMode() && err != HWC2::Error::None) {
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200203 return HWC2::Error::BadDisplay;
Roman Stratiienko3dacd472022-01-11 19:18:34 +0200204 }
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200205
Roman Stratiienko0137f862022-01-04 18:27:40 +0200206 return SetActiveConfig(configs_.preferred_config_id);
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200207}
208
209HWC2::Error HwcDisplay::AcceptDisplayChanges() {
210 for (std::pair<const hwc2_layer_t, HwcLayer> &l : layers_)
211 l.second.AcceptTypeChange();
212 return HWC2::Error::None;
213}
214
215HWC2::Error HwcDisplay::CreateLayer(hwc2_layer_t *layer) {
Roman Stratiienko4b2cc482022-02-21 14:53:58 +0200216 layers_.emplace(static_cast<hwc2_layer_t>(layer_idx_), HwcLayer(this));
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200217 *layer = static_cast<hwc2_layer_t>(layer_idx_);
218 ++layer_idx_;
219 return HWC2::Error::None;
220}
221
222HWC2::Error HwcDisplay::DestroyLayer(hwc2_layer_t layer) {
Roman Stratiienko3dacd472022-01-11 19:18:34 +0200223 if (!get_layer(layer)) {
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200224 return HWC2::Error::BadLayer;
Roman Stratiienko3dacd472022-01-11 19:18:34 +0200225 }
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200226
227 layers_.erase(layer);
228 return HWC2::Error::None;
229}
230
231HWC2::Error HwcDisplay::GetActiveConfig(hwc2_config_t *config) const {
Roman Stratiienkod0c035b2022-01-21 15:12:56 +0200232 if (configs_.hwc_configs.count(staged_mode_config_id_) == 0)
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200233 return HWC2::Error::BadConfig;
234
Roman Stratiienkod0c035b2022-01-21 15:12:56 +0200235 *config = staged_mode_config_id_;
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200236 return HWC2::Error::None;
237}
238
239HWC2::Error HwcDisplay::GetChangedCompositionTypes(uint32_t *num_elements,
240 hwc2_layer_t *layers,
241 int32_t *types) {
Roman Stratiienkof0c507f2022-01-17 18:29:24 +0200242 if (IsInHeadlessMode()) {
243 *num_elements = 0;
244 return HWC2::Error::None;
245 }
246
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200247 uint32_t num_changes = 0;
Roman Stratiienkoa7913de2022-10-20 13:18:57 +0300248 for (auto &l : layers_) {
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200249 if (l.second.IsTypeChanged()) {
250 if (layers && num_changes < *num_elements)
251 layers[num_changes] = l.first;
252 if (types && num_changes < *num_elements)
253 types[num_changes] = static_cast<int32_t>(l.second.GetValidatedType());
254 ++num_changes;
255 }
256 }
257 if (!layers && !types)
258 *num_elements = num_changes;
259 return HWC2::Error::None;
260}
261
262HWC2::Error HwcDisplay::GetClientTargetSupport(uint32_t width, uint32_t height,
263 int32_t /*format*/,
264 int32_t dataspace) {
Roman Stratiienkof0c507f2022-01-17 18:29:24 +0200265 if (IsInHeadlessMode()) {
266 return HWC2::Error::None;
267 }
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200268
Roman Stratiienkoa7913de2022-10-20 13:18:57 +0300269 auto min = pipeline_->device->GetMinResolution();
270 auto max = pipeline_->device->GetMaxResolution();
Roman Stratiienko3dacd472022-01-11 19:18:34 +0200271
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200272 if (width < min.first || height < min.second)
273 return HWC2::Error::Unsupported;
274
275 if (width > max.first || height > max.second)
276 return HWC2::Error::Unsupported;
277
278 if (dataspace != HAL_DATASPACE_UNKNOWN)
279 return HWC2::Error::Unsupported;
280
281 // TODO(nobody): Validate format can be handled by either GL or planes
282 return HWC2::Error::None;
283}
284
285HWC2::Error HwcDisplay::GetColorModes(uint32_t *num_modes, int32_t *modes) {
286 if (!modes)
287 *num_modes = 1;
288
289 if (modes)
290 *modes = HAL_COLOR_MODE_NATIVE;
291
292 return HWC2::Error::None;
293}
294
295HWC2::Error HwcDisplay::GetDisplayAttribute(hwc2_config_t config,
296 int32_t attribute_in,
297 int32_t *value) {
298 int conf = static_cast<int>(config);
299
Roman Stratiienko0137f862022-01-04 18:27:40 +0200300 if (configs_.hwc_configs.count(conf) == 0) {
Roman Stratiienko3dacd472022-01-11 19:18:34 +0200301 ALOGE("Could not find mode #%d", conf);
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200302 return HWC2::Error::BadConfig;
303 }
304
Roman Stratiienko0137f862022-01-04 18:27:40 +0200305 auto &hwc_config = configs_.hwc_configs[conf];
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200306
307 static const int32_t kUmPerInch = 25400;
Roman Stratiienkoa7913de2022-10-20 13:18:57 +0300308 auto mm_width = configs_.mm_width;
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200309 auto attribute = static_cast<HWC2::Attribute>(attribute_in);
310 switch (attribute) {
311 case HWC2::Attribute::Width:
Roman Stratiienkodf3120f2022-12-07 23:10:55 +0200312 *value = static_cast<int>(hwc_config.mode.GetRawMode().hdisplay);
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200313 break;
314 case HWC2::Attribute::Height:
Roman Stratiienkodf3120f2022-12-07 23:10:55 +0200315 *value = static_cast<int>(hwc_config.mode.GetRawMode().vdisplay);
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200316 break;
317 case HWC2::Attribute::VsyncPeriod:
318 // in nanoseconds
Roman Stratiienkodf3120f2022-12-07 23:10:55 +0200319 *value = static_cast<int>(1E9 / hwc_config.mode.GetVRefresh());
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200320 break;
Lucas Berthoudf686aa2024-08-28 16:15:38 +0000321 case HWC2::Attribute::DpiY:
322 // ideally this should be vdisplay/mm_heigth, however mm_height
323 // comes from edid parsing and is highly unreliable. Viewing the
324 // rarity of anisotropic displays, falling back to a single value
325 // for dpi yield more correct output.
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200326 case HWC2::Attribute::DpiX:
327 // Dots per 1000 inches
Roman Stratiienkodf3120f2022-12-07 23:10:55 +0200328 *value = mm_width ? int(hwc_config.mode.GetRawMode().hdisplay *
329 kUmPerInch / mm_width)
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200330 : -1;
331 break;
Roman Stratiienko6b405052022-12-10 19:09:10 +0200332#if __ANDROID_API__ > 29
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200333 case HWC2::Attribute::ConfigGroup:
334 /* Dispite ConfigGroup is a part of HWC2.4 API, framework
335 * able to request it even if service @2.1 is used */
Roman Stratiienkod0c035b2022-01-21 15:12:56 +0200336 *value = int(hwc_config.group_id);
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200337 break;
338#endif
339 default:
340 *value = -1;
341 return HWC2::Error::BadConfig;
342 }
343 return HWC2::Error::None;
344}
345
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200346HWC2::Error HwcDisplay::GetDisplayConfigs(uint32_t *num_configs,
347 hwc2_config_t *configs) {
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200348 uint32_t idx = 0;
Roman Stratiienko0137f862022-01-04 18:27:40 +0200349 for (auto &hwc_config : configs_.hwc_configs) {
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200350 if (hwc_config.second.disabled) {
351 continue;
352 }
353
354 if (configs != nullptr) {
355 if (idx >= *num_configs) {
356 break;
357 }
358 configs[idx] = hwc_config.second.id;
359 }
360
361 idx++;
362 }
363 *num_configs = idx;
364 return HWC2::Error::None;
365}
366
367HWC2::Error HwcDisplay::GetDisplayName(uint32_t *size, char *name) {
368 std::ostringstream stream;
Roman Stratiienko3dacd472022-01-11 19:18:34 +0200369 if (IsInHeadlessMode()) {
370 stream << "null-display";
371 } else {
372 stream << "display-" << GetPipe().connector->Get()->GetId();
373 }
Roman Stratiienkoa7913de2022-10-20 13:18:57 +0300374 auto string = stream.str();
375 auto length = string.length();
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200376 if (!name) {
377 *size = length;
378 return HWC2::Error::None;
379 }
380
381 *size = std::min<uint32_t>(static_cast<uint32_t>(length - 1), *size);
382 strncpy(name, string.c_str(), *size);
383 return HWC2::Error::None;
384}
385
386HWC2::Error HwcDisplay::GetDisplayRequests(int32_t * /*display_requests*/,
387 uint32_t *num_elements,
388 hwc2_layer_t * /*layers*/,
389 int32_t * /*layer_requests*/) {
390 // TODO(nobody): I think virtual display should request
391 // HWC2_DISPLAY_REQUEST_WRITE_CLIENT_TARGET_TO_OUTPUT here
392 *num_elements = 0;
393 return HWC2::Error::None;
394}
395
396HWC2::Error HwcDisplay::GetDisplayType(int32_t *type) {
397 *type = static_cast<int32_t>(type_);
398 return HWC2::Error::None;
399}
400
401HWC2::Error HwcDisplay::GetDozeSupport(int32_t *support) {
402 *support = 0;
403 return HWC2::Error::None;
404}
405
406HWC2::Error HwcDisplay::GetHdrCapabilities(uint32_t *num_types,
407 int32_t * /*types*/,
408 float * /*max_luminance*/,
409 float * /*max_average_luminance*/,
410 float * /*min_luminance*/) {
411 *num_types = 0;
412 return HWC2::Error::None;
413}
414
415/* Find API details at:
416 * https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=1767
Roman Stratiienkodd214942022-05-03 18:24:49 +0300417 *
418 * Called after PresentDisplay(), CLIENT is expecting release fence for the
419 * prior buffer (not the one assigned to the layer at the moment).
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200420 */
421HWC2::Error HwcDisplay::GetReleaseFences(uint32_t *num_elements,
422 hwc2_layer_t *layers,
423 int32_t *fences) {
Roman Stratiienkof0c507f2022-01-17 18:29:24 +0200424 if (IsInHeadlessMode()) {
425 *num_elements = 0;
426 return HWC2::Error::None;
427 }
428
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200429 uint32_t num_layers = 0;
430
Roman Stratiienkodd214942022-05-03 18:24:49 +0300431 for (auto &l : layers_) {
432 if (!l.second.GetPriorBufferScanOutFlag() || !present_fence_) {
433 continue;
434 }
435
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200436 ++num_layers;
Roman Stratiienkodd214942022-05-03 18:24:49 +0300437
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200438 if (layers == nullptr || fences == nullptr)
439 continue;
440
441 if (num_layers > *num_elements) {
442 ALOGW("Overflow num_elements %d/%d", num_layers, *num_elements);
443 return HWC2::Error::None;
444 }
445
446 layers[num_layers - 1] = l.first;
Roman Stratiienko76892782023-01-16 17:15:53 +0200447 fences[num_layers - 1] = DupFd(present_fence_);
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200448 }
449 *num_elements = num_layers;
Roman Stratiienkodd214942022-05-03 18:24:49 +0300450
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200451 return HWC2::Error::None;
452}
453
454HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) {
Roman Stratiienkof0c507f2022-01-17 18:29:24 +0200455 if (IsInHeadlessMode()) {
456 ALOGE("%s: Display is in headless mode, should never reach here", __func__);
457 return HWC2::Error::None;
458 }
459
Roman Stratiienko0da91bf2023-01-17 18:06:04 +0200460 a_args.color_matrix = color_matrix_;
461
Roman Stratiienkod2cc7382022-12-28 18:51:59 +0200462 uint32_t prev_vperiod_ns = 0;
463 GetDisplayVsyncPeriod(&prev_vperiod_ns);
Roman Stratiienkod0c035b2022-01-21 15:12:56 +0200464
465 auto mode_update_commited_ = false;
466 if (staged_mode_ &&
467 staged_mode_change_time_ <= ResourceManager::GetTimeMonotonicNs()) {
468 client_layer_.SetLayerDisplayFrame(
469 (hwc_rect_t){.left = 0,
470 .top = 0,
Roman Stratiienkodf3120f2022-12-07 23:10:55 +0200471 .right = int(staged_mode_->GetRawMode().hdisplay),
472 .bottom = int(staged_mode_->GetRawMode().vdisplay)});
Roman Stratiienkod0c035b2022-01-21 15:12:56 +0200473
474 configs_.active_config_id = staged_mode_config_id_;
475
476 a_args.display_mode = *staged_mode_;
477 if (!a_args.test_only) {
478 mode_update_commited_ = true;
479 }
480 }
481
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200482 // order the layers by z-order
483 bool use_client_layer = false;
484 uint32_t client_z_order = UINT32_MAX;
485 std::map<uint32_t, HwcLayer *> z_map;
486 for (std::pair<const hwc2_layer_t, HwcLayer> &l : layers_) {
487 switch (l.second.GetValidatedType()) {
488 case HWC2::Composition::Device:
Roman Stratiienkoa7913de2022-10-20 13:18:57 +0300489 z_map.emplace(l.second.GetZOrder(), &l.second);
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200490 break;
491 case HWC2::Composition::Client:
492 // Place it at the z_order of the lowest client layer
493 use_client_layer = true;
494 client_z_order = std::min(client_z_order, l.second.GetZOrder());
495 break;
496 default:
497 continue;
498 }
499 }
500 if (use_client_layer)
Roman Stratiienkoa7913de2022-10-20 13:18:57 +0300501 z_map.emplace(client_z_order, &client_layer_);
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200502
503 if (z_map.empty())
504 return HWC2::Error::BadLayer;
505
Roman Stratiienko4b2cc482022-02-21 14:53:58 +0200506 std::vector<LayerData> composition_layers;
507
508 /* Import & populate */
509 for (std::pair<const uint32_t, HwcLayer *> &l : z_map) {
Roman Stratiienko359a9d32023-01-16 17:41:07 +0200510 l.second->PopulateLayerData();
Roman Stratiienko4b2cc482022-02-21 14:53:58 +0200511 }
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200512
513 // now that they're ordered by z, add them to the composition
514 for (std::pair<const uint32_t, HwcLayer *> &l : z_map) {
Roman Stratiienko4b2cc482022-02-21 14:53:58 +0200515 if (!l.second->IsLayerUsableAsDevice()) {
516 /* This will be normally triggered on validation of the first frame
517 * containing CLIENT layer. At this moment client buffer is not yet
518 * provided by the CLIENT.
519 * This may be triggered once in HwcLayer lifecycle in case FB can't be
520 * imported. For example when non-contiguous buffer is imported into
521 * contiguous-only DRM/KMS driver.
522 */
523 return HWC2::Error::BadLayer;
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200524 }
Roman Stratiienko359a9d32023-01-16 17:41:07 +0200525 composition_layers.emplace_back(l.second->GetLayerData());
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200526 }
527
Roman Stratiienko9362cef2022-02-02 09:53:50 +0200528 /* Store plan to ensure shared planes won't be stolen by other display
529 * in between of ValidateDisplay() and PresentDisplay() calls
530 */
531 current_plan_ = DrmKmsPlan::CreateDrmKmsPlan(GetPipe(),
532 std::move(composition_layers));
Roman Stratiienkof2c060f2023-09-18 22:46:08 +0300533
534 if (type_ == HWC2::DisplayType::Virtual) {
535 a_args.writeback_fb = writeback_layer_->GetLayerData().fb;
536 a_args.writeback_release_fence = writeback_layer_->GetLayerData()
537 .acquire_fence;
538 }
539
Roman Stratiienko9362cef2022-02-02 09:53:50 +0200540 if (!current_plan_) {
541 if (!a_args.test_only) {
542 ALOGE("Failed to create DrmKmsPlan");
543 }
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200544 return HWC2::Error::BadConfig;
545 }
546
Roman Stratiienko9362cef2022-02-02 09:53:50 +0200547 a_args.composition = current_plan_;
548
Roman Stratiienkoa7913de2022-10-20 13:18:57 +0300549 auto ret = GetPipe().atomic_state_manager->ExecuteAtomicCommit(a_args);
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200550
551 if (ret) {
552 if (!a_args.test_only)
553 ALOGE("Failed to apply the frame composition ret=%d", ret);
554 return HWC2::Error::BadParameter;
555 }
556
Roman Stratiienkod0c035b2022-01-21 15:12:56 +0200557 if (mode_update_commited_) {
558 staged_mode_.reset();
559 vsync_tracking_en_ = false;
560 if (last_vsync_ts_ != 0) {
Drew Davenport93443182023-12-14 09:25:45 +0000561 hwc_->SendVsyncPeriodTimingChangedEventToClient(handle_,
562 last_vsync_ts_ +
563 prev_vperiod_ns);
Roman Stratiienkod0c035b2022-01-21 15:12:56 +0200564 }
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200565 }
566
567 return HWC2::Error::None;
568}
569
570/* Find API details at:
571 * https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=1805
572 */
Roman Stratiienkodd214942022-05-03 18:24:49 +0300573HWC2::Error HwcDisplay::PresentDisplay(int32_t *out_present_fence) {
Roman Stratiienkof0c507f2022-01-17 18:29:24 +0200574 if (IsInHeadlessMode()) {
Roman Stratiienkodd214942022-05-03 18:24:49 +0300575 *out_present_fence = -1;
Roman Stratiienkof0c507f2022-01-17 18:29:24 +0200576 return HWC2::Error::None;
577 }
Roman Stratiienko780f7da2022-01-10 16:04:15 +0200578 HWC2::Error ret{};
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200579
580 ++total_stats_.total_frames_;
581
582 AtomicCommitArgs a_args{};
583 ret = CreateComposition(a_args);
584
585 if (ret != HWC2::Error::None)
586 ++total_stats_.failed_kms_present_;
587
588 if (ret == HWC2::Error::BadLayer) {
589 // Can we really have no client or device layers?
Roman Stratiienkodd214942022-05-03 18:24:49 +0300590 *out_present_fence = -1;
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200591 return HWC2::Error::None;
592 }
593 if (ret != HWC2::Error::None)
594 return ret;
595
Roman Stratiienko76892782023-01-16 17:15:53 +0200596 this->present_fence_ = a_args.out_fence;
597 *out_present_fence = DupFd(a_args.out_fence);
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200598
Roman Stratiienko0da91bf2023-01-17 18:06:04 +0200599 // Reset the color matrix so we don't apply it over and over again.
600 color_matrix_ = {};
601
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200602 ++frame_no_;
603 return HWC2::Error::None;
604}
605
Roman Stratiienkod0c035b2022-01-21 15:12:56 +0200606HWC2::Error HwcDisplay::SetActiveConfigInternal(uint32_t config,
607 int64_t change_time) {
608 if (configs_.hwc_configs.count(config) == 0) {
609 ALOGE("Could not find active mode for %u", config);
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200610 return HWC2::Error::BadConfig;
611 }
612
Roman Stratiienkod0c035b2022-01-21 15:12:56 +0200613 staged_mode_ = configs_.hwc_configs[config].mode;
614 staged_mode_change_time_ = change_time;
615 staged_mode_config_id_ = config;
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200616
617 return HWC2::Error::None;
618}
619
Roman Stratiienkod0c035b2022-01-21 15:12:56 +0200620HWC2::Error HwcDisplay::SetActiveConfig(hwc2_config_t config) {
621 return SetActiveConfigInternal(config, ResourceManager::GetTimeMonotonicNs());
622}
623
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200624/* Find API details at:
625 * https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=1861
626 */
627HWC2::Error HwcDisplay::SetClientTarget(buffer_handle_t target,
628 int32_t acquire_fence,
629 int32_t dataspace,
630 hwc_region_t /*damage*/) {
631 client_layer_.SetLayerBuffer(target, acquire_fence);
632 client_layer_.SetLayerDataspace(dataspace);
633
634 /*
635 * target can be nullptr, this does mean the Composer Service is calling
636 * cleanDisplayResources() on after receiving HOTPLUG event. See more at:
637 * https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h;l=350;drc=944b68180b008456ed2eb4d4d329e33b19bd5166
638 */
639 if (target == nullptr) {
Roman Stratiienkoa32f9072022-05-13 12:12:20 +0300640 client_layer_.SwChainClearCache();
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200641 return HWC2::Error::None;
642 }
643
Roman Stratiienko5070d512022-05-30 13:41:20 +0300644 if (IsInHeadlessMode()) {
645 return HWC2::Error::None;
646 }
647
Roman Stratiienko359a9d32023-01-16 17:41:07 +0200648 client_layer_.PopulateLayerData();
Roman Stratiienko4b2cc482022-02-21 14:53:58 +0200649 if (!client_layer_.IsLayerUsableAsDevice()) {
650 ALOGE("Client layer must be always usable by DRM/KMS");
651 return HWC2::Error::BadLayer;
Roman Stratiienkoe9fbd8d2022-02-21 13:03:29 +0200652 }
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200653
Roman Stratiienko4b2cc482022-02-21 14:53:58 +0200654 auto &bi = client_layer_.GetLayerData().bi;
Roman Stratiienkoa7913de2022-10-20 13:18:57 +0300655 if (!bi) {
656 ALOGE("%s: Invalid state", __func__);
657 return HWC2::Error::BadLayer;
658 }
659
660 auto source_crop = (hwc_frect_t){.left = 0.0F,
661 .top = 0.0F,
662 .right = static_cast<float>(bi->width),
663 .bottom = static_cast<float>(bi->height)};
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200664 client_layer_.SetLayerSourceCrop(source_crop);
665
666 return HWC2::Error::None;
667}
668
669HWC2::Error HwcDisplay::SetColorMode(int32_t mode) {
670 if (mode < HAL_COLOR_MODE_NATIVE || mode > HAL_COLOR_MODE_BT2100_HLG)
671 return HWC2::Error::BadParameter;
672
673 if (mode != HAL_COLOR_MODE_NATIVE)
674 return HWC2::Error::Unsupported;
675
676 color_mode_ = mode;
677 return HWC2::Error::None;
678}
679
Roman Stratiienko0da91bf2023-01-17 18:06:04 +0200680#include <xf86drmMode.h>
681
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200682HWC2::Error HwcDisplay::SetColorTransform(const float *matrix, int32_t hint) {
683 if (hint < HAL_COLOR_TRANSFORM_IDENTITY ||
684 hint > HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA)
685 return HWC2::Error::BadParameter;
686
687 if (!matrix && hint == HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX)
688 return HWC2::Error::BadParameter;
689
690 color_transform_hint_ = static_cast<android_color_transform_t>(hint);
Roman Stratiienko0da91bf2023-01-17 18:06:04 +0200691
Roman Stratiienko5de61b52023-02-01 16:29:45 +0200692 if (IsInHeadlessMode())
693 return HWC2::Error::None;
694
Roman Stratiienko0da91bf2023-01-17 18:06:04 +0200695 if (!GetPipe().crtc->Get()->GetCtmProperty())
696 return HWC2::Error::None;
697
698 switch (color_transform_hint_) {
699 case HAL_COLOR_TRANSFORM_IDENTITY:
700 SetColorMarixToIdentity();
701 break;
702 case HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX:
703 color_matrix_ = std::make_shared<drm_color_ctm>();
704 /* DRM expects a 3x3 matrix, but the HAL provides a 4x4 matrix. */
705 for (int i = 0; i < kCtmCols; i++) {
706 for (int j = 0; j < kCtmRows; j++) {
707 constexpr int kInCtmRows = 4;
708 /* HAL matrix type is float, but DRM expects a s31.32 fix point */
Yongqin Liu152bc622023-01-29 00:48:10 +0800709 auto value = uint64_t(matrix[i * kInCtmRows + j] * float(1ULL << 32));
Roman Stratiienko0da91bf2023-01-17 18:06:04 +0200710 color_matrix_->matrix[i * kCtmRows + j] = value;
711 }
712 }
713 break;
714 default:
715 return HWC2::Error::Unsupported;
716 }
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200717
718 return HWC2::Error::None;
719}
720
Roman Stratiienko0da91bf2023-01-17 18:06:04 +0200721bool HwcDisplay::CtmByGpu() {
722 if (color_transform_hint_ == HAL_COLOR_TRANSFORM_IDENTITY)
723 return false;
724
725 if (GetPipe().crtc->Get()->GetCtmProperty())
726 return false;
727
Drew Davenport93443182023-12-14 09:25:45 +0000728 if (GetHwc()->GetResMan().GetCtmHandling() == CtmHandling::kDrmOrIgnore)
Roman Stratiienko0da91bf2023-01-17 18:06:04 +0200729 return false;
730
731 return true;
732}
733
Roman Stratiienkof2c060f2023-09-18 22:46:08 +0300734HWC2::Error HwcDisplay::SetOutputBuffer(buffer_handle_t buffer,
735 int32_t release_fence) {
736 writeback_layer_->SetLayerBuffer(buffer, release_fence);
737 writeback_layer_->PopulateLayerData();
738 if (!writeback_layer_->IsLayerUsableAsDevice()) {
739 ALOGE("Output layer must be always usable by DRM/KMS");
740 return HWC2::Error::BadLayer;
741 }
742 /* TODO: Check if format is supported by writeback connector */
743 return HWC2::Error::None;
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200744}
745
746HWC2::Error HwcDisplay::SetPowerMode(int32_t mode_in) {
747 auto mode = static_cast<HWC2::PowerMode>(mode_in);
Roman Stratiienkoccaf5162022-04-01 19:26:30 +0300748
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200749 AtomicCommitArgs a_args{};
750
751 switch (mode) {
752 case HWC2::PowerMode::Off:
753 a_args.active = false;
754 break;
755 case HWC2::PowerMode::On:
Roman Stratiienkoccaf5162022-04-01 19:26:30 +0300756 a_args.active = true;
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200757 break;
758 case HWC2::PowerMode::Doze:
759 case HWC2::PowerMode::DozeSuspend:
760 return HWC2::Error::Unsupported;
761 default:
John Stultzffe783c2024-02-14 10:51:27 -0800762 ALOGE("Incorrect power mode value (%d)\n", mode_in);
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200763 return HWC2::Error::BadParameter;
Roman Stratiienkoccaf5162022-04-01 19:26:30 +0300764 }
765
766 if (IsInHeadlessMode()) {
767 return HWC2::Error::None;
768 }
769
Jia Ren80566fe2022-11-17 17:26:00 +0800770 if (a_args.active && *a_args.active) {
Roman Stratiienkoccaf5162022-04-01 19:26:30 +0300771 /*
772 * Setting the display to active before we have a composition
773 * can break some drivers, so skip setting a_args.active to
774 * true, as the next composition frame will implicitly activate
775 * the display
776 */
777 return GetPipe().atomic_state_manager->ActivateDisplayUsingDPMS() == 0
778 ? HWC2::Error::None
779 : HWC2::Error::BadParameter;
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200780 };
781
Roman Stratiienkoa7913de2022-10-20 13:18:57 +0300782 auto err = GetPipe().atomic_state_manager->ExecuteAtomicCommit(a_args);
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200783 if (err) {
784 ALOGE("Failed to apply the dpms composition err=%d", err);
785 return HWC2::Error::BadParameter;
786 }
787 return HWC2::Error::None;
788}
789
790HWC2::Error HwcDisplay::SetVsyncEnabled(int32_t enabled) {
Roman Stratiienkof2c060f2023-09-18 22:46:08 +0300791 if (type_ == HWC2::DisplayType::Virtual) {
792 return HWC2::Error::None;
793 }
794
Roman Stratiienko099c3112022-01-20 11:50:54 +0200795 vsync_event_en_ = HWC2_VSYNC_ENABLE == enabled;
796 if (vsync_event_en_) {
Roman Stratiienkod2cc7382022-12-28 18:51:59 +0200797 vsync_worker_->VSyncControl(true);
Roman Stratiienko099c3112022-01-20 11:50:54 +0200798 }
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200799 return HWC2::Error::None;
800}
801
802HWC2::Error HwcDisplay::ValidateDisplay(uint32_t *num_types,
803 uint32_t *num_requests) {
Roman Stratiienkof0c507f2022-01-17 18:29:24 +0200804 if (IsInHeadlessMode()) {
805 *num_types = *num_requests = 0;
806 return HWC2::Error::None;
807 }
Roman Stratiienkodd214942022-05-03 18:24:49 +0300808
809 /* In current drm_hwc design in case previous frame layer was not validated as
810 * a CLIENT, it is used by display controller (Front buffer). We have to store
811 * this state to provide the CLIENT with the release fences for such buffers.
812 */
813 for (auto &l : layers_) {
814 l.second.SetPriorBufferScanOutFlag(l.second.GetValidatedType() !=
815 HWC2::Composition::Client);
816 }
817
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200818 return backend_->ValidateDisplay(this, num_types, num_requests);
819}
820
821std::vector<HwcLayer *> HwcDisplay::GetOrderLayersByZPos() {
822 std::vector<HwcLayer *> ordered_layers;
823 ordered_layers.reserve(layers_.size());
824
825 for (auto &[handle, layer] : layers_) {
826 ordered_layers.emplace_back(&layer);
827 }
828
829 std::sort(std::begin(ordered_layers), std::end(ordered_layers),
830 [](const HwcLayer *lhs, const HwcLayer *rhs) {
831 return lhs->GetZOrder() < rhs->GetZOrder();
832 });
833
834 return ordered_layers;
835}
836
Roman Stratiienko099c3112022-01-20 11:50:54 +0200837HWC2::Error HwcDisplay::GetDisplayVsyncPeriod(
838 uint32_t *outVsyncPeriod /* ns */) {
839 return GetDisplayAttribute(configs_.active_config_id,
840 HWC2_ATTRIBUTE_VSYNC_PERIOD,
841 (int32_t *)(outVsyncPeriod));
842}
843
Roman Stratiienko6b405052022-12-10 19:09:10 +0200844#if __ANDROID_API__ > 29
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200845HWC2::Error HwcDisplay::GetDisplayConnectionType(uint32_t *outType) {
Roman Stratiienko456e2d62022-01-29 01:17:39 +0200846 if (IsInHeadlessMode()) {
847 *outType = static_cast<uint32_t>(HWC2::DisplayConnectionType::Internal);
848 return HWC2::Error::None;
849 }
850 /* Primary display should be always internal,
851 * otherwise SF will be unhappy and will crash
852 */
Roman Stratiienko19c162f2022-02-01 09:35:08 +0200853 if (GetPipe().connector->Get()->IsInternal() || handle_ == kPrimaryDisplay)
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200854 *outType = static_cast<uint32_t>(HWC2::DisplayConnectionType::Internal);
Roman Stratiienko19c162f2022-02-01 09:35:08 +0200855 else if (GetPipe().connector->Get()->IsExternal())
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200856 *outType = static_cast<uint32_t>(HWC2::DisplayConnectionType::External);
857 else
858 return HWC2::Error::BadConfig;
859
860 return HWC2::Error::None;
861}
862
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200863HWC2::Error HwcDisplay::SetActiveConfigWithConstraints(
Roman Stratiienkod0c035b2022-01-21 15:12:56 +0200864 hwc2_config_t config,
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200865 hwc_vsync_period_change_constraints_t *vsyncPeriodChangeConstraints,
866 hwc_vsync_period_change_timeline_t *outTimeline) {
Roman Stratiienkof2c060f2023-09-18 22:46:08 +0300867 if (type_ == HWC2::DisplayType::Virtual) {
868 return HWC2::Error::None;
869 }
870
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200871 if (vsyncPeriodChangeConstraints == nullptr || outTimeline == nullptr) {
872 return HWC2::Error::BadParameter;
873 }
874
Roman Stratiienkod0c035b2022-01-21 15:12:56 +0200875 uint32_t current_vsync_period{};
876 GetDisplayVsyncPeriod(&current_vsync_period);
877
878 if (vsyncPeriodChangeConstraints->seamlessRequired) {
879 return HWC2::Error::SeamlessNotAllowed;
880 }
881
882 outTimeline->refreshTimeNanos = vsyncPeriodChangeConstraints
883 ->desiredTimeNanos -
884 current_vsync_period;
885 auto ret = SetActiveConfigInternal(config, outTimeline->refreshTimeNanos);
886 if (ret != HWC2::Error::None) {
887 return ret;
888 }
889
890 outTimeline->refreshRequired = true;
891 outTimeline->newVsyncAppliedTimeNanos = vsyncPeriodChangeConstraints
892 ->desiredTimeNanos;
893
894 last_vsync_ts_ = 0;
895 vsync_tracking_en_ = true;
Roman Stratiienkod2cc7382022-12-28 18:51:59 +0200896 vsync_worker_->VSyncControl(true);
Roman Stratiienkod0c035b2022-01-21 15:12:56 +0200897
898 return HWC2::Error::None;
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200899}
900
901HWC2::Error HwcDisplay::SetAutoLowLatencyMode(bool /*on*/) {
902 return HWC2::Error::Unsupported;
903}
904
905HWC2::Error HwcDisplay::GetSupportedContentTypes(
906 uint32_t *outNumSupportedContentTypes,
907 const uint32_t *outSupportedContentTypes) {
908 if (outSupportedContentTypes == nullptr)
909 *outNumSupportedContentTypes = 0;
910
911 return HWC2::Error::None;
912}
913
914HWC2::Error HwcDisplay::SetContentType(int32_t contentType) {
915 if (contentType != HWC2_CONTENT_TYPE_NONE)
916 return HWC2::Error::Unsupported;
917
918 /* TODO: Map to the DRM Connector property:
919 * https://elixir.bootlin.com/linux/v5.4-rc5/source/drivers/gpu/drm/drm_connector.c#L809
920 */
921
922 return HWC2::Error::None;
923}
924#endif
925
Roman Stratiienko6b405052022-12-10 19:09:10 +0200926#if __ANDROID_API__ > 28
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200927HWC2::Error HwcDisplay::GetDisplayIdentificationData(uint8_t *outPort,
928 uint32_t *outDataSize,
929 uint8_t *outData) {
Roman Stratiienko3dacd472022-01-11 19:18:34 +0200930 if (IsInHeadlessMode()) {
Roman Stratiienkof87d8082022-05-06 11:33:56 +0300931 return HWC2::Error::Unsupported;
Roman Stratiienko3dacd472022-01-11 19:18:34 +0200932 }
Roman Stratiienkof87d8082022-05-06 11:33:56 +0300933
Roman Stratiienko19c162f2022-02-01 09:35:08 +0200934 auto blob = GetPipe().connector->Get()->GetEdidBlob();
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200935 if (!blob) {
Roman Stratiienkof87d8082022-05-06 11:33:56 +0300936 return HWC2::Error::Unsupported;
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200937 }
938
Roman Stratiienkof87d8082022-05-06 11:33:56 +0300939 *outPort = handle_; /* TDOD(nobody): What should be here? */
940
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200941 if (outData) {
942 *outDataSize = std::min(*outDataSize, blob->length);
943 memcpy(outData, blob->data, *outDataSize);
944 } else {
945 *outDataSize = blob->length;
946 }
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200947
948 return HWC2::Error::None;
949}
950
951HWC2::Error HwcDisplay::GetDisplayCapabilities(uint32_t *outNumCapabilities,
Roman Stratiienko0da91bf2023-01-17 18:06:04 +0200952 uint32_t *outCapabilities) {
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200953 if (outNumCapabilities == nullptr) {
954 return HWC2::Error::BadParameter;
955 }
956
Roman Stratiienko0da91bf2023-01-17 18:06:04 +0200957 bool skip_ctm = false;
958
959 // Skip client CTM if user requested DRM_OR_IGNORE
Drew Davenport93443182023-12-14 09:25:45 +0000960 if (GetHwc()->GetResMan().GetCtmHandling() == CtmHandling::kDrmOrIgnore)
Roman Stratiienko0da91bf2023-01-17 18:06:04 +0200961 skip_ctm = true;
962
963 // Skip client CTM if DRM can handle it
964 if (!skip_ctm && !IsInHeadlessMode() &&
965 GetPipe().crtc->Get()->GetCtmProperty())
966 skip_ctm = true;
967
968 if (!skip_ctm) {
969 *outNumCapabilities = 0;
970 return HWC2::Error::None;
971 }
972
973 *outNumCapabilities = 1;
974 if (outCapabilities) {
975 outCapabilities[0] = HWC2_DISPLAY_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM;
976 }
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200977
978 return HWC2::Error::None;
979}
980
981HWC2::Error HwcDisplay::GetDisplayBrightnessSupport(bool *supported) {
982 *supported = false;
983 return HWC2::Error::None;
984}
985
986HWC2::Error HwcDisplay::SetDisplayBrightness(float /* brightness */) {
987 return HWC2::Error::Unsupported;
988}
989
Roman Stratiienko6b405052022-12-10 19:09:10 +0200990#endif /* __ANDROID_API__ > 28 */
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200991
Roman Stratiienko6b405052022-12-10 19:09:10 +0200992#if __ANDROID_API__ > 27
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200993
994HWC2::Error HwcDisplay::GetRenderIntents(
995 int32_t mode, uint32_t *outNumIntents,
996 int32_t * /*android_render_intent_v1_1_t*/ outIntents) {
997 if (mode != HAL_COLOR_MODE_NATIVE) {
998 return HWC2::Error::BadParameter;
999 }
1000
1001 if (outIntents == nullptr) {
1002 *outNumIntents = 1;
1003 return HWC2::Error::None;
1004 }
1005 *outNumIntents = 1;
1006 outIntents[0] = HAL_RENDER_INTENT_COLORIMETRIC;
1007 return HWC2::Error::None;
1008}
1009
1010HWC2::Error HwcDisplay::SetColorModeWithIntent(int32_t mode, int32_t intent) {
1011 if (intent < HAL_RENDER_INTENT_COLORIMETRIC ||
1012 intent > HAL_RENDER_INTENT_TONE_MAP_ENHANCE)
1013 return HWC2::Error::BadParameter;
1014
1015 if (mode < HAL_COLOR_MODE_NATIVE || mode > HAL_COLOR_MODE_BT2100_HLG)
1016 return HWC2::Error::BadParameter;
1017
1018 if (mode != HAL_COLOR_MODE_NATIVE)
1019 return HWC2::Error::Unsupported;
1020
1021 if (intent != HAL_RENDER_INTENT_COLORIMETRIC)
1022 return HWC2::Error::Unsupported;
1023
1024 color_mode_ = mode;
1025 return HWC2::Error::None;
1026}
1027
Roman Stratiienko6b405052022-12-10 19:09:10 +02001028#endif /* __ANDROID_API__ > 27 */
Roman Stratiienko3627beb2022-01-04 16:02:55 +02001029
1030const Backend *HwcDisplay::backend() const {
1031 return backend_.get();
1032}
1033
1034void HwcDisplay::set_backend(std::unique_ptr<Backend> backend) {
1035 backend_ = std::move(backend);
1036}
1037
Roman Stratiienko3627beb2022-01-04 16:02:55 +02001038} // namespace android