blob: 12c091a7e53c8ed3db3cc0838e5e42d94e1ad0ff [file] [log] [blame]
Dennis Tsiang33f0ece2023-11-29 12:45:04 +00001/*
Drew Davenport5951b112024-08-05 09:44:27 -06002 * Copyright (C) 2024 The Android Open Source Project
Dennis Tsiang33f0ece2023-11-29 12:45:04 +00003 *
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
Drew Davenport5951b112024-08-05 09:44:27 -060017#define LOG_TAG "drmhwc"
Dennis Tsiang33f0ece2023-11-29 12:45:04 +000018#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
19
20#include "ComposerClient.h"
21
Drew Davenport5951b112024-08-05 09:44:27 -060022#include <cinttypes>
Dennis Tsiang1a966202024-01-24 12:46:33 +000023#include <cmath>
Drew Davenport5951b112024-08-05 09:44:27 -060024#include <memory>
25#include <unordered_map>
26#include <vector>
27
Drew Davenporta241a772024-09-24 11:26:30 -060028#include <aidl/android/hardware/graphics/common/Transform.h>
29#include <aidl/android/hardware/graphics/composer3/ClientTarget.h>
30#include <aidl/android/hardware/graphics/composer3/Composition.h>
31#include <aidl/android/hardware/graphics/composer3/DisplayRequest.h>
32#include <aidl/android/hardware/graphics/composer3/IComposerClient.h>
33#include <aidl/android/hardware/graphics/composer3/PowerMode.h>
34#include <aidl/android/hardware/graphics/composer3/PresentOrValidate.h>
35#include <aidl/android/hardware/graphics/composer3/RenderIntent.h>
36#include <aidlcommonsupport/NativeHandle.h>
37#include <android-base/logging.h>
38#include <android/binder_auto_utils.h>
39#include <android/binder_ibinder_platform.h>
40#include <cutils/native_handle.h>
41#include <hardware/hwcomposer2.h>
42#include <hardware/hwcomposer_defs.h>
43
44#include "bufferinfo/BufferInfo.h"
Drew Davenport5951b112024-08-05 09:44:27 -060045#include "hwc2_device/HwcDisplay.h"
Drew Davenportf7e88332024-09-06 12:54:38 -060046#include "hwc2_device/HwcDisplayConfigs.h"
Drew Davenport5951b112024-08-05 09:44:27 -060047#include "hwc2_device/HwcLayer.h"
48#include "hwc3/DrmHwcThree.h"
49#include "hwc3/Utils.h"
50
51using ::android::HwcDisplay;
Drew Davenportf7e88332024-09-06 12:54:38 -060052using ::android::HwcDisplayConfigs;
Drew Davenporta241a772024-09-24 11:26:30 -060053using ::android::HwcLayer;
Dennis Tsiang33f0ece2023-11-29 12:45:04 +000054
55#include "utils/log.h"
56
57namespace aidl::android::hardware::graphics::composer3::impl {
Drew Davenport5951b112024-08-05 09:44:27 -060058namespace {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +000059
Drew Davenport5951b112024-08-05 09:44:27 -060060// clang-format off
61constexpr std::array<float, 16> kIdentityMatrix = {
62 1.0F, 0.0F, 0.0F, 0.0F,
63 0.0F, 1.0F, 0.0F, 0.0F,
64 0.0F, 0.0F, 1.0F, 0.0F,
65 0.0F, 0.0F, 0.0F, 1.0F,
66};
67// clang-format on
Dennis Tsiang33f0ece2023-11-29 12:45:04 +000068
Drew Davenporta241a772024-09-24 11:26:30 -060069std::optional<BufferBlendMode> AidlToBlendMode(
70 const std::optional<ParcelableBlendMode>& aidl_blend_mode) {
71 if (!aidl_blend_mode) {
72 return std::nullopt;
73 }
74
75 switch (aidl_blend_mode->blendMode) {
76 case common::BlendMode::NONE:
77 return BufferBlendMode::kNone;
78 case common::BlendMode::PREMULTIPLIED:
79 return BufferBlendMode::kPreMult;
80 case common::BlendMode::COVERAGE:
81 return BufferBlendMode::kCoverage;
82 case common::BlendMode::INVALID:
83 ALOGE("Invalid BlendMode");
84 return std::nullopt;
85 }
86}
87
Drew Davenportac9681e2024-09-24 12:17:34 -060088std::optional<BufferColorSpace> AidlToColorSpace(
89 const std::optional<ParcelableDataspace>& dataspace) {
90 if (!dataspace) {
91 return std::nullopt;
92 }
93
94 int32_t standard = static_cast<int32_t>(dataspace->dataspace) &
95 static_cast<int32_t>(common::Dataspace::STANDARD_MASK);
96 switch (standard) {
97 case static_cast<int32_t>(common::Dataspace::STANDARD_BT709):
98 return BufferColorSpace::kItuRec709;
99 case static_cast<int32_t>(common::Dataspace::STANDARD_BT601_625):
100 case static_cast<int32_t>(common::Dataspace::STANDARD_BT601_625_UNADJUSTED):
101 case static_cast<int32_t>(common::Dataspace::STANDARD_BT601_525):
102 case static_cast<int32_t>(common::Dataspace::STANDARD_BT601_525_UNADJUSTED):
103 return BufferColorSpace::kItuRec601;
104 case static_cast<int32_t>(common::Dataspace::STANDARD_BT2020):
105 case static_cast<int32_t>(
106 common::Dataspace::STANDARD_BT2020_CONSTANT_LUMINANCE):
107 return BufferColorSpace::kItuRec2020;
108 default:
109 ALOGE("Unsupported standard: %d", standard);
110 return std::nullopt;
111 }
112}
113
114std::optional<BufferSampleRange> AidlToSampleRange(
115 const std::optional<ParcelableDataspace>& dataspace) {
116 if (!dataspace) {
117 return std::nullopt;
118 }
119
120 int32_t sample_range = static_cast<int32_t>(dataspace->dataspace) &
121 static_cast<int32_t>(common::Dataspace::RANGE_MASK);
122 switch (sample_range) {
123 case static_cast<int32_t>(common::Dataspace::RANGE_FULL):
124 return BufferSampleRange::kFullRange;
125 case static_cast<int32_t>(common::Dataspace::RANGE_LIMITED):
126 return BufferSampleRange::kLimitedRange;
127 default:
128 ALOGE("Unsupported sample range: %d", sample_range);
129 return std::nullopt;
130 }
131}
132
Drew Davenport5951b112024-08-05 09:44:27 -0600133} // namespace
134
135ComposerClient::ComposerClient() {
136 DEBUG_FUNC();
137}
138
139bool ComposerClient::Init() {
140 DEBUG_FUNC();
141 composer_resources_ = ComposerResources::Create();
142 if (composer_resources_) {
143 hwc_ = std::make_unique<DrmHwcThree>(composer_resources_.get());
144 }
145 return composer_resources_ != nullptr;
146}
147
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000148ComposerClient::~ComposerClient() {
149 DEBUG_FUNC();
Drew Davenport1ac3b622024-09-05 10:59:16 -0600150 {
151 // First Deinit the displays to start shutting down the Display's dependent
152 // threads such as VSyncWorker.
153 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
154 hwc_->DeinitDisplays();
155 }
156 // Sleep to wait for threads to complete and exit.
157 const int time_for_threads_to_exit_us = 200000;
158 usleep(time_for_threads_to_exit_us);
159 {
160 // Hold the lock while destructing the hwc_ and the objects that it owns.
161 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
162 hwc_.reset();
163 }
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000164 LOG(DEBUG) << "removed composer client";
165}
166
Drew Davenport5951b112024-08-05 09:44:27 -0600167ndk::ScopedAStatus ComposerClient::createLayer(int64_t display_id,
168 int32_t buffer_slot_count,
169 int64_t* layer_id) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000170 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600171 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
172
173 HwcDisplay* display = GetDisplay(display_id);
174 if (display == nullptr) {
175 return ToBinderStatus(hwc3::Error::kBadDisplay);
176 }
177
178 hwc2_layer_t hwc2_layer_id = 0;
179 auto err = Hwc2toHwc3Error(display->CreateLayer(&hwc2_layer_id));
180 if (err != hwc3::Error::kNone) {
181 return ToBinderStatus(err);
182 }
183
184 const int64_t created_layer_id = Hwc2LayerToHwc3(hwc2_layer_id);
185 err = composer_resources_->AddLayer(display_id, created_layer_id,
186 buffer_slot_count);
187 if (err != hwc3::Error::kNone) {
188 destroyLayer(display_id, created_layer_id);
189 return ToBinderStatus(err);
190 }
191
192 *layer_id = created_layer_id;
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000193 return ndk::ScopedAStatus::ok();
194}
195
196ndk::ScopedAStatus ComposerClient::createVirtualDisplay(
Drew Davenport5951b112024-08-05 09:44:27 -0600197 int32_t width, int32_t height, AidlPixelFormat format_hint,
198 int32_t output_buffer_slot_count, VirtualDisplay* out_display) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000199 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600200 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
201
202 hwc2_display_t hwc2_display_id = 0;
203 // TODO: Format is currently not used in drm_hwcomposer.
204 int32_t hwc2_format = 0;
205 auto err = Hwc2toHwc3Error(hwc_->CreateVirtualDisplay(width, height,
206 &hwc2_format,
207 &hwc2_display_id));
208 if (err != hwc3::Error::kNone) {
209 return ToBinderStatus(err);
210 }
211
212 const int64_t created_display_id = Hwc2DisplayToHwc3(hwc2_display_id);
213 err = composer_resources_->AddVirtualDisplay(hwc2_display_id,
214 output_buffer_slot_count);
215 if (err != hwc3::Error::kNone) {
216 hwc_->DestroyVirtualDisplay(hwc2_display_id);
217 return ToBinderStatus(err);
218 }
219
220 out_display->display = created_display_id;
221 out_display->format = format_hint;
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000222 return ndk::ScopedAStatus::ok();
223}
224
Drew Davenport5951b112024-08-05 09:44:27 -0600225ndk::ScopedAStatus ComposerClient::destroyLayer(int64_t display_id,
226 int64_t layer_id) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000227 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600228 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
229 HwcDisplay* display = GetDisplay(display_id);
230 if (display == nullptr) {
231 return ToBinderStatus(hwc3::Error::kBadDisplay);
232 }
233
234 auto err = Hwc2toHwc3Error(display->DestroyLayer(Hwc3LayerToHwc2(layer_id)));
235 if (err != hwc3::Error::kNone) {
236 return ToBinderStatus(err);
237 }
238
239 err = composer_resources_->RemoveLayer(display_id, layer_id);
240 return ToBinderStatus(err);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000241}
242
Drew Davenport5951b112024-08-05 09:44:27 -0600243ndk::ScopedAStatus ComposerClient::destroyVirtualDisplay(int64_t display_id) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000244 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600245 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
246 auto err = Hwc2toHwc3Error(hwc_->DestroyVirtualDisplay(display_id));
247 return ToBinderStatus(err);
248}
249
250hwc3::Error ComposerClient::ValidateDisplayInternal(
251 HwcDisplay& display, std::vector<int64_t>* out_changed_layers,
252 std::vector<Composition>* out_composition_types,
253 int32_t* out_display_request_mask,
254 std::vector<int64_t>* out_requested_layers,
255 std::vector<int32_t>* out_request_masks,
256 ClientTargetProperty* /*out_client_target_property*/,
257 DimmingStage* /*out_dimming_stage*/) {
258 DEBUG_FUNC();
259
260 uint32_t num_types = 0;
261 uint32_t num_requests = 0;
262 const HWC2::Error hwc2_error = display.ValidateDisplay(&num_types,
263 &num_requests);
264
265 /* Check if display has pending changes and no errors */
266 if (hwc2_error != HWC2::Error::None &&
267 hwc2_error != HWC2::Error::HasChanges) {
268 return Hwc2toHwc3Error(hwc2_error);
269 }
270
Drew Davenport3f4469f2024-10-03 10:01:51 -0600271 hwc3::Error error = Hwc2toHwc3Error(
272 display.GetChangedCompositionTypes(&num_types, nullptr, nullptr));
273 if (error != hwc3::Error::kNone) {
274 return error;
275 }
276
Drew Davenport5951b112024-08-05 09:44:27 -0600277 std::vector<hwc2_layer_t> hwc_changed_layers(num_types);
278 std::vector<int32_t> hwc_composition_types(num_types);
Drew Davenport3f4469f2024-10-03 10:01:51 -0600279 error = Hwc2toHwc3Error(
Drew Davenport5951b112024-08-05 09:44:27 -0600280 display.GetChangedCompositionTypes(&num_types, hwc_changed_layers.data(),
281 hwc_composition_types.data()));
282 if (error != hwc3::Error::kNone) {
283 return error;
284 }
285
286 int32_t display_reqs = 0;
287 out_request_masks->resize(num_requests);
288 std::vector<hwc2_layer_t> hwc_requested_layers(num_requests);
289 error = Hwc2toHwc3Error(
290 display.GetDisplayRequests(&display_reqs, &num_requests,
291 hwc_requested_layers.data(),
292 out_request_masks->data()));
293 if (error != hwc3::Error::kNone) {
294 return error;
295 }
296
297 for (const auto& layer : hwc_changed_layers) {
298 out_changed_layers->emplace_back(Hwc2LayerToHwc3(layer));
299 }
300 for (const auto& type : hwc_composition_types) {
301 out_composition_types->emplace_back(Hwc2CompositionTypeToHwc3(type));
302 }
303 for (const auto& layer : hwc_requested_layers) {
304 out_requested_layers->emplace_back(Hwc2LayerToHwc3(layer));
305 }
306 *out_display_request_mask = display_reqs;
307
308 /* Client target property/dimming stage unsupported */
309 return hwc3::Error::kNone;
310}
311
312hwc3::Error ComposerClient::PresentDisplayInternal(
313 uint64_t display_id, ::android::base::unique_fd& out_display_fence,
314 std::unordered_map<int64_t, ::android::base::unique_fd>&
315 out_release_fences) {
316 DEBUG_FUNC();
317 auto* display = GetDisplay(display_id);
318 if (display == nullptr) {
319 return hwc3::Error::kBadDisplay;
320 }
321
322 if (composer_resources_->MustValidateDisplay(display_id)) {
323 return hwc3::Error::kNotValidated;
324 }
325
326 int32_t present_fence = -1;
327 auto error = Hwc2toHwc3Error(display->PresentDisplay(&present_fence));
328 if (error != hwc3::Error::kNone) {
329 return error;
330 }
331 out_display_fence.reset(present_fence);
332
333 uint32_t release_fence_count = 0;
334 error = Hwc2toHwc3Error(
335 display->GetReleaseFences(&release_fence_count, nullptr, nullptr));
336 if (error != hwc3::Error::kNone) {
337 return error;
338 }
339
340 std::vector<hwc2_layer_t> hwc_layers(release_fence_count);
341 std::vector<int32_t> hwc_fences(release_fence_count);
342 error = Hwc2toHwc3Error(display->GetReleaseFences(&release_fence_count,
343 hwc_layers.data(),
344 hwc_fences.data()));
345 if (error != hwc3::Error::kNone) {
346 return error;
347 }
348
349 for (size_t i = 0; i < hwc_layers.size(); i++) {
350 auto layer = Hwc2LayerToHwc3(hwc_layers[i]);
351 out_release_fences[layer] = ::android::base::unique_fd{hwc_fences[i]};
352 }
353
354 return hwc3::Error::kNone;
355}
356
357::android::HwcDisplay* ComposerClient::GetDisplay(uint64_t display_id) {
358 return hwc_->GetDisplay(display_id);
359}
360
361void ComposerClient::DispatchLayerCommand(int64_t display_id,
362 const LayerCommand& command) {
363 auto* display = GetDisplay(display_id);
364 if (display == nullptr) {
365 cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
366 return;
367 }
368
369 auto* layer = display->get_layer(command.layer);
370 if (layer == nullptr) {
371 cmd_result_writer_->AddError(hwc3::Error::kBadLayer);
372 return;
373 }
374
375 HwcLayerWrapper layer_wrapper{command.layer, layer};
376 if (command.buffer) {
377 ExecuteSetLayerBuffer(display_id, layer_wrapper, *command.buffer);
378 }
Drew Davenporta241a772024-09-24 11:26:30 -0600379 HwcLayer::LayerProperties properties;
380 properties.blend_mode = AidlToBlendMode(command.blendMode);
Drew Davenportac9681e2024-09-24 12:17:34 -0600381 properties.color_space = AidlToColorSpace(command.dataspace);
382 properties.sample_range = AidlToSampleRange(command.dataspace);
Drew Davenporta241a772024-09-24 11:26:30 -0600383 layer->SetLayerProperties(properties);
384
Drew Davenport5951b112024-08-05 09:44:27 -0600385 if (command.composition) {
386 ExecuteSetLayerComposition(display_id, layer_wrapper, *command.composition);
387 }
Drew Davenport5951b112024-08-05 09:44:27 -0600388 if (command.displayFrame) {
389 ExecuteSetLayerDisplayFrame(display_id, layer_wrapper,
390 *command.displayFrame);
391 }
392 if (command.planeAlpha) {
393 ExecuteSetLayerPlaneAlpha(display_id, layer_wrapper, *command.planeAlpha);
394 }
395 if (command.sourceCrop) {
396 ExecuteSetLayerSourceCrop(display_id, layer_wrapper, *command.sourceCrop);
397 }
398 if (command.transform) {
399 ExecuteSetLayerTransform(display_id, layer_wrapper, *command.transform);
400 }
401 if (command.z) {
402 ExecuteSetLayerZOrder(display_id, layer_wrapper, *command.z);
403 }
404 if (command.brightness) {
405 ExecuteSetLayerBrightness(display_id, layer_wrapper, *command.brightness);
406 }
407
408 // Some unsupported functionality returns kUnsupported, and others
409 // are just a no-op.
410 // TODO: Audit whether some of these should actually return kUnsupported
411 // instead.
412 if (command.sidebandStream) {
413 cmd_result_writer_->AddError(hwc3::Error::kUnsupported);
414 }
415 // TODO: Blocking region handling missing.
416 // TODO: Layer surface damage.
417 // TODO: Layer visible region.
418 // TODO: Per-frame metadata.
419 // TODO: Layer color transform.
420 // TODO: Layer cursor position.
421 // TODO: Layer color.
422}
423
424void ComposerClient::ExecuteDisplayCommand(const DisplayCommand& command) {
425 const int64_t display_id = command.display;
426 if (hwc_->GetDisplay(display_id) == nullptr) {
427 cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
428 return;
429 }
430
431 for (const auto& layer_cmd : command.layers) {
432 DispatchLayerCommand(command.display, layer_cmd);
433 }
434
435 if (command.brightness) {
436 ExecuteSetDisplayBrightness(command.display, *command.brightness);
437 }
438 if (command.colorTransformMatrix) {
439 ExecuteSetDisplayColorTransform(command.display,
440 *command.colorTransformMatrix);
441 }
442 if (command.clientTarget) {
443 ExecuteSetDisplayClientTarget(command.display, *command.clientTarget);
444 }
445 if (command.virtualDisplayOutputBuffer) {
446 ExecuteSetDisplayOutputBuffer(command.display,
447 *command.virtualDisplayOutputBuffer);
448 }
449 if (command.validateDisplay) {
450 ExecuteValidateDisplay(command.display, command.expectedPresentTime);
451 }
452 if (command.acceptDisplayChanges) {
453 ExecuteAcceptDisplayChanges(command.display);
454 }
455 if (command.presentDisplay) {
456 ExecutePresentDisplay(command.display);
457 }
458 if (command.presentOrValidateDisplay) {
459 ExecutePresentOrValidateDisplay(command.display,
460 command.expectedPresentTime);
461 }
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000462}
463
464ndk::ScopedAStatus ComposerClient::executeCommands(
Drew Davenport5951b112024-08-05 09:44:27 -0600465 const std::vector<DisplayCommand>& commands,
466 std::vector<CommandResultPayload>* results) {
Drew Davenport49965852024-09-05 10:59:40 -0600467 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
468 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600469 cmd_result_writer_ = std::make_unique<CommandResultWriter>(results);
470 for (const auto& cmd : commands) {
471 ExecuteDisplayCommand(cmd);
472 cmd_result_writer_->IncrementCommand();
473 }
474 cmd_result_writer_.reset();
475
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000476 return ndk::ScopedAStatus::ok();
477}
478
Drew Davenport5951b112024-08-05 09:44:27 -0600479ndk::ScopedAStatus ComposerClient::getActiveConfig(int64_t display_id,
480 int32_t* config) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000481 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600482 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
483 HwcDisplay* display = GetDisplay(display_id);
484 if (display == nullptr) {
485 return ToBinderStatus(hwc3::Error::kBadDisplay);
486 }
487
488 uint32_t hwc2_config = 0;
489 const hwc3::Error error = Hwc2toHwc3Error(
490 display->GetActiveConfig(&hwc2_config));
491 if (error != hwc3::Error::kNone) {
492 return ToBinderStatus(error);
493 }
494 *config = Hwc2ConfigIdToHwc3(hwc2_config);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000495 return ndk::ScopedAStatus::ok();
496}
497
498ndk::ScopedAStatus ComposerClient::getColorModes(
Drew Davenport5951b112024-08-05 09:44:27 -0600499 int64_t display_id, std::vector<ColorMode>* color_modes) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000500 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600501 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
502 HwcDisplay* display = GetDisplay(display_id);
503 if (display == nullptr) {
504 return ToBinderStatus(hwc3::Error::kBadDisplay);
505 }
506
507 uint32_t num_modes = 0;
508 auto error = Hwc2toHwc3Error(display->GetColorModes(&num_modes, nullptr));
509 if (error != hwc3::Error::kNone) {
510 return ToBinderStatus(error);
511 }
512
513 std::vector<int32_t> hwc2_color_modes(num_modes);
514 error = Hwc2toHwc3Error(
515 display->GetColorModes(&num_modes, hwc2_color_modes.data()));
516 if (error != hwc3::Error::kNone) {
517 return ToBinderStatus(error);
518 }
519
520 for (const auto& mode : hwc2_color_modes) {
521 color_modes->push_back(Hwc2ColorModeToHwc3(mode));
522 }
523
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000524 return ndk::ScopedAStatus::ok();
525}
526
527ndk::ScopedAStatus ComposerClient::getDataspaceSaturationMatrix(
Drew Davenport5951b112024-08-05 09:44:27 -0600528 common::Dataspace dataspace, std::vector<float>* matrix) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000529 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600530 if (dataspace != common::Dataspace::SRGB_LINEAR) {
531 return ToBinderStatus(hwc3::Error::kBadParameter);
532 }
533
534 matrix->clear();
535 matrix->insert(matrix->begin(), kIdentityMatrix.begin(),
536 kIdentityMatrix.end());
537
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000538 return ndk::ScopedAStatus::ok();
539}
540
541ndk::ScopedAStatus ComposerClient::getDisplayAttribute(
Drew Davenport5951b112024-08-05 09:44:27 -0600542 int64_t display_id, int32_t config, DisplayAttribute attribute,
543 int32_t* value) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000544 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600545 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
546 HwcDisplay* display = GetDisplay(display_id);
547 if (display == nullptr) {
548 return ToBinderStatus(hwc3::Error::kBadDisplay);
549 }
550
551 const hwc3::Error error = Hwc2toHwc3Error(
552 display->GetDisplayAttribute(Hwc3ConfigIdToHwc2(config),
553 Hwc3DisplayAttributeToHwc2(attribute),
554 value));
555 return ToBinderStatus(error);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000556}
557
558ndk::ScopedAStatus ComposerClient::getDisplayCapabilities(
Drew Davenport5951b112024-08-05 09:44:27 -0600559 int64_t display_id, std::vector<DisplayCapability>* caps) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000560 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600561 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
562 HwcDisplay* display = GetDisplay(display_id);
563 if (display == nullptr) {
564 return ToBinderStatus(hwc3::Error::kBadDisplay);
565 }
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000566
Drew Davenport5951b112024-08-05 09:44:27 -0600567 uint32_t num_capabilities = 0;
568 hwc3::Error error = Hwc2toHwc3Error(
569 display->GetDisplayCapabilities(&num_capabilities, nullptr));
570 if (error != hwc3::Error::kNone) {
571 return ToBinderStatus(error);
572 }
573
574 std::vector<uint32_t> out_caps(num_capabilities);
575 error = Hwc2toHwc3Error(
576 display->GetDisplayCapabilities(&num_capabilities, out_caps.data()));
577 if (error != hwc3::Error::kNone) {
578 return ToBinderStatus(error);
579 }
580
581 caps->reserve(num_capabilities);
582 for (const auto cap : out_caps) {
583 caps->emplace_back(Hwc2DisplayCapabilityToHwc3(cap));
584 }
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000585 return ndk::ScopedAStatus::ok();
586}
587
588ndk::ScopedAStatus ComposerClient::getDisplayConfigs(
Drew Davenport5951b112024-08-05 09:44:27 -0600589 int64_t display_id, std::vector<int32_t>* configs) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000590 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600591 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
592 HwcDisplay* display = GetDisplay(display_id);
593 if (display == nullptr) {
594 return ToBinderStatus(hwc3::Error::kBadDisplay);
595 }
596
597 uint32_t num_configs = 0;
598 hwc3::Error error = Hwc2toHwc3Error(
Drew Davenportf7e88332024-09-06 12:54:38 -0600599 display->LegacyGetDisplayConfigs(&num_configs, nullptr));
Drew Davenport5951b112024-08-05 09:44:27 -0600600 if (error != hwc3::Error::kNone) {
601 return ToBinderStatus(error);
602 }
603
604 std::vector<hwc2_config_t> out_configs(num_configs);
605 error = Hwc2toHwc3Error(
Drew Davenportf7e88332024-09-06 12:54:38 -0600606 display->LegacyGetDisplayConfigs(&num_configs, out_configs.data()));
Drew Davenport5951b112024-08-05 09:44:27 -0600607 if (error != hwc3::Error::kNone) {
608 return ToBinderStatus(error);
609 }
610
611 configs->reserve(num_configs);
612 for (const auto config : out_configs) {
613 configs->emplace_back(Hwc2ConfigIdToHwc3(config));
614 }
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000615 return ndk::ScopedAStatus::ok();
616}
617
618ndk::ScopedAStatus ComposerClient::getDisplayConnectionType(
Drew Davenport5951b112024-08-05 09:44:27 -0600619 int64_t display_id, DisplayConnectionType* type) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000620 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600621 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
622 HwcDisplay* display = GetDisplay(display_id);
623 if (display == nullptr) {
624 return ToBinderStatus(hwc3::Error::kBadDisplay);
625 }
626
627 uint32_t out_type = 0;
628 const hwc3::Error error = Hwc2toHwc3Error(
629 display->GetDisplayConnectionType(&out_type));
630 if (error != hwc3::Error::kNone) {
631 return ToBinderStatus(error);
632 }
633
634 *type = Hwc2DisplayConnectionTypeToHwc3(out_type);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000635 return ndk::ScopedAStatus::ok();
636}
637
638ndk::ScopedAStatus ComposerClient::getDisplayIdentificationData(
Drew Davenport5951b112024-08-05 09:44:27 -0600639 int64_t display_id, DisplayIdentification* id) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000640 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600641 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
642 HwcDisplay* display = GetDisplay(display_id);
643 if (display == nullptr) {
644 return ToBinderStatus(hwc3::Error::kBadDisplay);
645 }
646
647 uint8_t port = 0;
648 uint32_t data_size = 0;
649 hwc3::Error error = Hwc2toHwc3Error(
650 display->GetDisplayIdentificationData(&port, &data_size, nullptr));
651 if (error != hwc3::Error::kNone) {
652 return ToBinderStatus(error);
653 }
654
655 id->data.resize(data_size);
656 error = Hwc2toHwc3Error(
657 display->GetDisplayIdentificationData(&port, &data_size,
658 id->data.data()));
659 if (error != hwc3::Error::kNone) {
660 return ToBinderStatus(error);
661 }
662
663 id->port = static_cast<int8_t>(port);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000664 return ndk::ScopedAStatus::ok();
665}
666
Drew Davenport5951b112024-08-05 09:44:27 -0600667ndk::ScopedAStatus ComposerClient::getDisplayName(int64_t display_id,
668 std::string* name) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000669 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600670 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
671 HwcDisplay* display = GetDisplay(display_id);
672 if (display == nullptr) {
673 return ToBinderStatus(hwc3::Error::kBadDisplay);
674 }
675
676 uint32_t size = 0;
677 auto error = Hwc2toHwc3Error(display->GetDisplayName(&size, nullptr));
678 if (error != hwc3::Error::kNone) {
679 return ToBinderStatus(error);
680 }
681
682 name->resize(size);
683 error = Hwc2toHwc3Error(display->GetDisplayName(&size, name->data()));
684 return ToBinderStatus(error);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000685}
686
687ndk::ScopedAStatus ComposerClient::getDisplayVsyncPeriod(
Drew Davenport5951b112024-08-05 09:44:27 -0600688 int64_t display_id, int32_t* vsync_period) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000689 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600690 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
691 HwcDisplay* display = GetDisplay(display_id);
692 if (display == nullptr) {
693 return ToBinderStatus(hwc3::Error::kBadDisplay);
694 }
695
696 uint32_t hwc2_vsync_period = 0;
697 auto error = Hwc2toHwc3Error(
698 display->GetDisplayVsyncPeriod(&hwc2_vsync_period));
699 if (error != hwc3::Error::kNone) {
700 return ToBinderStatus(error);
701 }
702
703 *vsync_period = static_cast<int32_t>(hwc2_vsync_period);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000704 return ndk::ScopedAStatus::ok();
705}
706
707ndk::ScopedAStatus ComposerClient::getDisplayedContentSample(
Drew Davenport5951b112024-08-05 09:44:27 -0600708 int64_t /*display_id*/, int64_t /*max_frames*/, int64_t /*timestamp*/,
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000709 DisplayContentSample* /*samples*/) {
710 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600711 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000712}
713
714ndk::ScopedAStatus ComposerClient::getDisplayedContentSamplingAttributes(
Drew Davenport5951b112024-08-05 09:44:27 -0600715 int64_t /*display_id*/, DisplayContentSamplingAttributes* /*attrs*/) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000716 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600717 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000718}
719
720ndk::ScopedAStatus ComposerClient::getDisplayPhysicalOrientation(
Drew Davenport5951b112024-08-05 09:44:27 -0600721 int64_t display_id, common::Transform* orientation) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000722 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600723 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
724 HwcDisplay* display = GetDisplay(display_id);
725 if (display == nullptr) {
726 return ToBinderStatus(hwc3::Error::kBadDisplay);
727 }
728
729 *orientation = common::Transform::NONE;
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000730 return ndk::ScopedAStatus::ok();
731}
732
Drew Davenport5951b112024-08-05 09:44:27 -0600733ndk::ScopedAStatus ComposerClient::getHdrCapabilities(int64_t display_id,
734 HdrCapabilities* caps) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000735 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600736 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
737 HwcDisplay* display = GetDisplay(display_id);
738 if (display == nullptr) {
739 return ToBinderStatus(hwc3::Error::kBadDisplay);
740 }
741
742 /* No HDR capabilities */
743 caps->types.clear();
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000744 return ndk::ScopedAStatus::ok();
745}
746
Drew Davenport5951b112024-08-05 09:44:27 -0600747ndk::ScopedAStatus ComposerClient::getMaxVirtualDisplayCount(int32_t* count) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000748 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600749 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
750 *count = static_cast<int32_t>(hwc_->GetMaxVirtualDisplayCount());
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000751 return ndk::ScopedAStatus::ok();
752}
753
754ndk::ScopedAStatus ComposerClient::getPerFrameMetadataKeys(
Drew Davenport5951b112024-08-05 09:44:27 -0600755 int64_t /*display_id*/, std::vector<PerFrameMetadataKey>* /*keys*/) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000756 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600757 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000758}
759
760ndk::ScopedAStatus ComposerClient::getReadbackBufferAttributes(
Drew Davenport5951b112024-08-05 09:44:27 -0600761 int64_t /*display_id*/, ReadbackBufferAttributes* /*attrs*/) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000762 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600763 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000764}
765
766ndk::ScopedAStatus ComposerClient::getReadbackBufferFence(
Drew Davenport5951b112024-08-05 09:44:27 -0600767 int64_t /*display_id*/, ndk::ScopedFileDescriptor* /*acquireFence*/) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000768 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600769 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000770}
771
772ndk::ScopedAStatus ComposerClient::getRenderIntents(
Drew Davenport5951b112024-08-05 09:44:27 -0600773 int64_t display_id, ColorMode mode, std::vector<RenderIntent>* intents) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000774 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600775 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
776 HwcDisplay* display = GetDisplay(display_id);
777 if (display == nullptr) {
778 return ToBinderStatus(hwc3::Error::kBadDisplay);
779 }
780
781 const int32_t hwc2_color_mode = Hwc3ColorModeToHwc2(mode);
782 uint32_t out_num_intents = 0;
783 auto error = Hwc2toHwc3Error(
784 display->GetRenderIntents(hwc2_color_mode, &out_num_intents, nullptr));
785 if (error != hwc3::Error::kNone) {
786 return ToBinderStatus(error);
787 }
788
789 std::vector<int32_t> out_intents(out_num_intents);
790 error = Hwc2toHwc3Error(display->GetRenderIntents(hwc2_color_mode,
791 &out_num_intents,
792 out_intents.data()));
793 if (error != hwc3::Error::kNone) {
794 return ToBinderStatus(error);
795 }
796
797 intents->reserve(out_num_intents);
798 for (const auto intent : out_intents) {
799 intents->emplace_back(Hwc2RenderIntentToHwc3(intent));
800 }
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000801 return ndk::ScopedAStatus::ok();
802}
803
804ndk::ScopedAStatus ComposerClient::getSupportedContentTypes(
Drew Davenport5951b112024-08-05 09:44:27 -0600805 int64_t display_id, std::vector<ContentType>* types) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000806 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600807 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
808 HwcDisplay* display = GetDisplay(display_id);
809 if (display == nullptr) {
810 return ToBinderStatus(hwc3::Error::kBadDisplay);
811 }
812
Drew Davenport8d38dc72024-09-24 12:26:07 -0600813 // Support for ContentType is not implemented.
814 types->clear();
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000815 return ndk::ScopedAStatus::ok();
816}
817
818ndk::ScopedAStatus ComposerClient::getDisplayDecorationSupport(
Drew Davenport5951b112024-08-05 09:44:27 -0600819 int64_t /*display_id*/,
820 std::optional<common::DisplayDecorationSupport>* /*support_struct*/) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000821 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600822 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000823}
824
825ndk::ScopedAStatus ComposerClient::registerCallback(
Drew Davenport5951b112024-08-05 09:44:27 -0600826 const std::shared_ptr<IComposerCallback>& callback) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000827 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600828 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
829 // This function is specified to be called exactly once.
830 hwc_->Init(callback);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000831 return ndk::ScopedAStatus::ok();
832}
833
Drew Davenport5951b112024-08-05 09:44:27 -0600834ndk::ScopedAStatus ComposerClient::setActiveConfig(int64_t display_id,
835 int32_t config) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000836 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600837 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
838 HwcDisplay* display = GetDisplay(display_id);
839 if (display == nullptr) {
840 return ToBinderStatus(hwc3::Error::kBadDisplay);
841 }
842
843 return ToBinderStatus(Hwc2toHwc3Error(display->SetActiveConfig(config)));
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000844}
845
846ndk::ScopedAStatus ComposerClient::setActiveConfigWithConstraints(
Drew Davenport5951b112024-08-05 09:44:27 -0600847 int64_t display_id, int32_t config,
848 const VsyncPeriodChangeConstraints& constraints,
849 VsyncPeriodChangeTimeline* timeline) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000850 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600851 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
852 HwcDisplay* display = GetDisplay(display_id);
853 if (display == nullptr) {
854 return ToBinderStatus(hwc3::Error::kBadDisplay);
855 }
856
857 hwc_vsync_period_change_constraints_t hwc2_constraints;
858 hwc2_constraints.desiredTimeNanos = constraints.desiredTimeNanos;
859 hwc2_constraints.seamlessRequired = static_cast<uint8_t>(
860 constraints.seamlessRequired);
861
862 hwc_vsync_period_change_timeline_t hwc2_timeline{};
863 auto error = Hwc2toHwc3Error(
864 display->SetActiveConfigWithConstraints(config, &hwc2_constraints,
865 &hwc2_timeline));
866 if (error != hwc3::Error::kNone) {
867 return ToBinderStatus(error);
868 }
869
870 timeline->refreshTimeNanos = hwc2_timeline.refreshTimeNanos;
871 timeline->newVsyncAppliedTimeNanos = hwc2_timeline.newVsyncAppliedTimeNanos;
872 timeline->refreshRequired = static_cast<bool>(hwc2_timeline.refreshRequired);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000873 return ndk::ScopedAStatus::ok();
874}
875
Drew Davenport5951b112024-08-05 09:44:27 -0600876ndk::ScopedAStatus ComposerClient::setBootDisplayConfig(int64_t /*display_id*/,
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000877 int32_t /*config*/) {
878 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600879 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000880}
881
Drew Davenport5951b112024-08-05 09:44:27 -0600882ndk::ScopedAStatus ComposerClient::clearBootDisplayConfig(
883 int64_t /*display_id*/) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000884 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600885 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000886}
887
888ndk::ScopedAStatus ComposerClient::getPreferredBootDisplayConfig(
Drew Davenport5951b112024-08-05 09:44:27 -0600889 int64_t /*display_id*/, int32_t* /*config*/) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000890 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600891 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000892}
893
Drew Davenport5951b112024-08-05 09:44:27 -0600894ndk::ScopedAStatus ComposerClient::setAutoLowLatencyMode(int64_t display_id,
895 bool on) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000896 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600897 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
898 HwcDisplay* display = GetDisplay(display_id);
899 if (display == nullptr) {
900 return ToBinderStatus(hwc3::Error::kBadDisplay);
901 }
902
903 auto error = Hwc2toHwc3Error(display->SetAutoLowLatencyMode(on));
904 return ToBinderStatus(error);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000905}
906
Drew Davenport5951b112024-08-05 09:44:27 -0600907ndk::ScopedAStatus ComposerClient::setClientTargetSlotCount(int64_t display_id,
908 int32_t count) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000909 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600910 return ToBinderStatus(
911 composer_resources_->SetDisplayClientTargetCacheSize(display_id, count));
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000912}
913
Drew Davenport5951b112024-08-05 09:44:27 -0600914ndk::ScopedAStatus ComposerClient::setColorMode(int64_t display_id,
915 ColorMode mode,
916 RenderIntent intent) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000917 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600918 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
919 HwcDisplay* display = GetDisplay(display_id);
920 if (display == nullptr) {
921 return ToBinderStatus(hwc3::Error::kBadDisplay);
922 }
923
924 auto error = display->SetColorModeWithIntent(Hwc3ColorModeToHwc2(mode),
925 Hwc3RenderIntentToHwc2(intent));
926 return ToBinderStatus(Hwc2toHwc3Error(error));
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000927}
928
Drew Davenport5951b112024-08-05 09:44:27 -0600929ndk::ScopedAStatus ComposerClient::setContentType(int64_t display_id,
930 ContentType type) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000931 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600932 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
933 HwcDisplay* display = GetDisplay(display_id);
934 if (display == nullptr) {
935 return ToBinderStatus(hwc3::Error::kBadDisplay);
936 }
937
Drew Davenport8d38dc72024-09-24 12:26:07 -0600938 if (type == ContentType::NONE) {
939 return ndk::ScopedAStatus::ok();
940 }
941 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000942}
943
944ndk::ScopedAStatus ComposerClient::setDisplayedContentSamplingEnabled(
Drew Davenport5951b112024-08-05 09:44:27 -0600945 int64_t /*display_id*/, bool /*enable*/,
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000946 FormatColorComponent /*componentMask*/, int64_t /*maxFrames*/) {
947 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600948 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000949}
950
Drew Davenport5951b112024-08-05 09:44:27 -0600951ndk::ScopedAStatus ComposerClient::setPowerMode(int64_t display_id,
952 PowerMode mode) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000953 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600954 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
955 HwcDisplay* display = GetDisplay(display_id);
956 if (display == nullptr) {
957 return ToBinderStatus(hwc3::Error::kBadDisplay);
958 }
959
Dennis Tsiang1a966202024-01-24 12:46:33 +0000960 if (mode == PowerMode::ON_SUSPEND) {
961 return ToBinderStatus(hwc3::Error::kUnsupported);
962 }
963
Drew Davenport5951b112024-08-05 09:44:27 -0600964 auto error = display->SetPowerMode(Hwc3PowerModeToHwc2(mode));
965 return ToBinderStatus(Hwc2toHwc3Error(error));
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000966}
967
968ndk::ScopedAStatus ComposerClient::setReadbackBuffer(
Drew Davenport5951b112024-08-05 09:44:27 -0600969 int64_t /*display_id*/, const AidlNativeHandle& /*aidlBuffer*/,
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000970 const ndk::ScopedFileDescriptor& /*releaseFence*/) {
971 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600972 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000973}
974
Drew Davenport5951b112024-08-05 09:44:27 -0600975ndk::ScopedAStatus ComposerClient::setVsyncEnabled(int64_t display_id,
976 bool enabled) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000977 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600978 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
979 HwcDisplay* display = GetDisplay(display_id);
980 if (display == nullptr) {
981 return ToBinderStatus(hwc3::Error::kBadDisplay);
982 }
983
984 auto error = display->SetVsyncEnabled(static_cast<int32_t>(enabled));
985 return ToBinderStatus(Hwc2toHwc3Error(error));
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000986}
987
Drew Davenport5951b112024-08-05 09:44:27 -0600988ndk::ScopedAStatus ComposerClient::setIdleTimerEnabled(int64_t /*display_id*/,
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000989 int32_t /*timeout*/) {
990 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600991 return ToBinderStatus(hwc3::Error::kUnsupported);
992}
993
Drew Davenport7f1761b2024-08-20 10:09:43 -0600994ndk::ScopedAStatus ComposerClient::getOverlaySupport(
995 OverlayProperties* /*out_overlay_properties*/) {
996 return ToBinderStatus(hwc3::Error::kUnsupported);
997}
998
999ndk::ScopedAStatus ComposerClient::getHdrConversionCapabilities(
1000 std::vector<common::HdrConversionCapability>* /*out_capabilities*/) {
1001 return ToBinderStatus(hwc3::Error::kUnsupported);
1002}
1003
1004ndk::ScopedAStatus ComposerClient::setHdrConversionStrategy(
1005 const common::HdrConversionStrategy& /*conversion_strategy*/,
1006 common::Hdr* /*out_hdr*/) {
1007 return ToBinderStatus(hwc3::Error::kUnsupported);
1008}
1009
1010ndk::ScopedAStatus ComposerClient::setRefreshRateChangedCallbackDebugEnabled(
1011 int64_t /*display*/, bool /*enabled*/) {
1012 return ToBinderStatus(hwc3::Error::kUnsupported);
1013}
1014
1015ndk::ScopedAStatus ComposerClient::getDisplayConfigurations(
Drew Davenportf7e88332024-09-06 12:54:38 -06001016 int64_t display_id, int32_t /*max_frame_interval_ns*/,
Drew Davenport7f1761b2024-08-20 10:09:43 -06001017 std::vector<DisplayConfiguration>* configurations) {
Drew Davenportf7e88332024-09-06 12:54:38 -06001018 DEBUG_FUNC();
1019 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
1020 HwcDisplay* display = GetDisplay(display_id);
1021 if (display == nullptr) {
1022 return ToBinderStatus(hwc3::Error::kBadDisplay);
1023 }
1024
1025 const HwcDisplayConfigs& configs = display->GetDisplayConfigs();
1026 for (const auto& [id, config] : configs.hwc_configs) {
Drew Davenportf7e88332024-09-06 12:54:38 -06001027 configurations->emplace_back(
1028 DisplayConfiguration{.configId = static_cast<int32_t>(config.id),
1029 .width = config.mode.GetRawMode().hdisplay,
1030 .height = config.mode.GetRawMode().vdisplay,
1031 .configGroup = static_cast<int32_t>(
1032 config.group_id),
Drew Davenport8053f2e2024-10-02 13:44:41 -06001033 .vsyncPeriod = config.mode.GetVSyncPeriodNs()});
Drew Davenportf7e88332024-09-06 12:54:38 -06001034
1035 if (configs.mm_width != 0) {
1036 // ideally this should be vdisplay/mm_heigth, however mm_height
1037 // comes from edid parsing and is highly unreliable. Viewing the
1038 // rarity of anisotropic displays, falling back to a single value
1039 // for dpi yield more correct output.
1040 static const float kMmPerInch = 25.4;
1041 float dpi = float(config.mode.GetRawMode().hdisplay) * kMmPerInch /
1042 float(configs.mm_width);
1043 configurations->back().dpi = {.x = dpi, .y = dpi};
1044 }
1045
1046 // TODO: Populate vrrConfig.
1047 }
1048 return ndk::ScopedAStatus::ok();
Drew Davenport7f1761b2024-08-20 10:09:43 -06001049}
1050
1051ndk::ScopedAStatus ComposerClient::notifyExpectedPresent(
1052 int64_t /*display*/, const ClockMonotonicTimestamp& /*expected_present_time*/,
1053 int32_t /*frame_interval_ns*/) {
1054 return ToBinderStatus(hwc3::Error::kUnsupported);
1055}
1056
Drew Davenport5951b112024-08-05 09:44:27 -06001057std::string ComposerClient::Dump() {
1058 uint32_t size = 0;
1059 hwc_->Dump(&size, nullptr);
1060
1061 std::string buffer(size, '\0');
1062 hwc_->Dump(&size, &buffer.front());
1063 return buffer;
Dennis Tsiang33f0ece2023-11-29 12:45:04 +00001064}
1065
1066::ndk::SpAIBinder ComposerClient::createBinder() {
1067 auto binder = BnComposerClient::createBinder();
1068 AIBinder_setInheritRt(binder.get(), true);
1069 return binder;
1070}
1071
Drew Davenport5951b112024-08-05 09:44:27 -06001072void ComposerClient::ExecuteSetLayerBuffer(int64_t display_id,
1073 HwcLayerWrapper& layer,
1074 const Buffer& buffer) {
1075 buffer_handle_t imported_buffer = nullptr;
1076
1077 auto releaser = composer_resources_->CreateResourceReleaser(true);
1078 auto err = composer_resources_->GetLayerBuffer(display_id, layer.layer_id,
1079 buffer, &imported_buffer,
1080 releaser.get());
1081 if (err != hwc3::Error::kNone) {
1082 cmd_result_writer_->AddError(err);
1083 return;
1084 }
1085
1086 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
1087 auto fence_fd = const_cast<ndk::ScopedFileDescriptor&>(buffer.fence)
1088 .release();
1089 err = Hwc2toHwc3Error(layer.layer->SetLayerBuffer(imported_buffer, fence_fd));
1090 if (err != hwc3::Error::kNone) {
1091 cmd_result_writer_->AddError(err);
1092 }
1093}
1094
Drew Davenport5951b112024-08-05 09:44:27 -06001095void ComposerClient::ExecuteSetLayerComposition(
1096 int64_t /*display_id*/, HwcLayerWrapper& layer,
1097 const ParcelableComposition& composition) {
1098 hwc3::Error error = hwc3::Error::kNone;
1099 switch (composition.composition) {
1100 // Unsupported composition types should set an error for the current
1101 // DisplayCommand.
1102 case Composition::DISPLAY_DECORATION:
1103 case Composition::SIDEBAND:
1104 error = hwc3::Error::kUnsupported;
1105 break;
1106 default:
1107 error = Hwc2toHwc3Error(layer.layer->SetLayerCompositionType(
1108 Hwc3CompositionToHwc2(composition.composition)));
1109 }
1110 if (error != hwc3::Error::kNone) {
1111 cmd_result_writer_->AddError(error);
1112 }
1113}
1114
Drew Davenport5951b112024-08-05 09:44:27 -06001115void ComposerClient::ExecuteSetLayerDisplayFrame(int64_t /*display_id*/,
1116 HwcLayerWrapper& layer,
1117 const common::Rect& rect) {
1118 const hwc_rect_t hwc2_rect{rect.left, rect.top, rect.right, rect.bottom};
1119 auto err = Hwc2toHwc3Error(layer.layer->SetLayerDisplayFrame(hwc2_rect));
1120 if (err != hwc3::Error::kNone) {
1121 cmd_result_writer_->AddError(err);
1122 }
1123}
1124void ComposerClient::ExecuteSetLayerPlaneAlpha(int64_t /*display_id*/,
1125 HwcLayerWrapper& layer,
1126 const PlaneAlpha& plane_alpha) {
1127 auto err = Hwc2toHwc3Error(
1128 layer.layer->SetLayerPlaneAlpha(plane_alpha.alpha));
1129 if (err != hwc3::Error::kNone) {
1130 cmd_result_writer_->AddError(err);
1131 }
1132}
1133
1134void ComposerClient::ExecuteSetLayerSourceCrop(
1135 int64_t /*display_id*/, HwcLayerWrapper& layer,
1136 const common::FRect& source_crop) {
1137 const hwc_frect_t rect{source_crop.left, source_crop.top, source_crop.right,
1138 source_crop.bottom};
1139 auto err = Hwc2toHwc3Error(layer.layer->SetLayerSourceCrop(rect));
1140 if (err != hwc3::Error::kNone) {
1141 cmd_result_writer_->AddError(err);
1142 }
1143}
1144void ComposerClient::ExecuteSetLayerTransform(
1145 int64_t /*display_id*/, HwcLayerWrapper& layer,
1146 const ParcelableTransform& transform) {
1147 auto err = Hwc2toHwc3Error(
1148 layer.layer->SetLayerTransform(Hwc3TransformToHwc2(transform.transform)));
1149 if (err != hwc3::Error::kNone) {
1150 cmd_result_writer_->AddError(err);
1151 }
1152}
1153void ComposerClient::ExecuteSetLayerZOrder(int64_t /*display_id*/,
1154 HwcLayerWrapper& layer,
1155 const ZOrder& z_order) {
1156 auto err = Hwc2toHwc3Error(layer.layer->SetLayerZOrder(z_order.z));
1157 if (err != hwc3::Error::kNone) {
1158 cmd_result_writer_->AddError(err);
1159 }
1160}
1161
1162void ComposerClient::ExecuteSetLayerBrightness(
1163 int64_t /*display_id*/, HwcLayerWrapper& /*layer*/,
1164 const LayerBrightness& brightness) {
1165 if (std::signbit(brightness.brightness) ||
1166 std::isnan(brightness.brightness)) {
1167 cmd_result_writer_->AddError(hwc3::Error::kBadParameter);
1168 }
1169}
1170
1171void ComposerClient::ExecuteSetDisplayBrightness(
1172 uint64_t display_id, const DisplayBrightness& command) {
1173 auto* display = GetDisplay(display_id);
1174 if (display == nullptr) {
1175 cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
1176 return;
1177 }
1178
1179 auto error = Hwc2toHwc3Error(
1180 display->SetDisplayBrightness(command.brightness));
1181 if (error != hwc3::Error::kNone) {
1182 cmd_result_writer_->AddError(error);
1183 }
1184}
1185void ComposerClient::ExecuteSetDisplayColorTransform(
1186 uint64_t display_id, const std::vector<float>& matrix) {
1187 auto* display = GetDisplay(display_id);
1188 if (display == nullptr) {
1189 cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
1190 return;
1191 }
1192
1193 auto almost_equal = [](auto a, auto b) {
1194 const float epsilon = 0.001F;
1195 return std::abs(a - b) < epsilon;
1196 };
1197 const bool is_identity = std::equal(matrix.begin(), matrix.end(),
1198 kIdentityMatrix.begin(), almost_equal);
1199
1200 const int32_t hint = is_identity ? HAL_COLOR_TRANSFORM_IDENTITY
1201 : HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX;
1202
1203 auto error = Hwc2toHwc3Error(display->SetColorTransform(matrix.data(), hint));
1204 if (error != hwc3::Error::kNone) {
1205 cmd_result_writer_->AddError(error);
1206 }
1207}
1208void ComposerClient::ExecuteSetDisplayClientTarget(
1209 uint64_t display_id, const ClientTarget& command) {
1210 auto* display = GetDisplay(display_id);
1211 if (display == nullptr) {
1212 cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
1213 return;
1214 }
1215
1216 hwc_region_t damage_regions;
1217 damage_regions.numRects = command.damage.size();
1218
1219 std::vector<hwc_rect_t> regions(command.damage.size());
1220 for (const auto& region : command.damage) {
1221 regions.push_back({region.left, region.top, region.right, region.bottom});
1222 }
1223 damage_regions.rects = regions.data();
1224
1225 buffer_handle_t imported_buffer = nullptr;
1226 auto buf_releaser = composer_resources_->CreateResourceReleaser(true);
1227
1228 auto error = composer_resources_->GetDisplayClientTarget(display_id,
1229 command.buffer,
1230 &imported_buffer,
1231 buf_releaser.get());
1232 if (error != hwc3::Error::kNone) {
1233 cmd_result_writer_->AddError(error);
1234 return;
1235 }
1236
1237 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
1238 auto fence = const_cast<::ndk::ScopedFileDescriptor&>(command.buffer.fence)
1239 .release();
1240 error = Hwc2toHwc3Error(
1241 display->SetClientTarget(imported_buffer, fence,
1242 Hwc3DataspaceToHwc2(command.dataspace),
1243 damage_regions));
1244 if (error != hwc3::Error::kNone) {
1245 cmd_result_writer_->AddError(error);
1246 }
1247}
1248
1249void ComposerClient::ExecuteSetDisplayOutputBuffer(uint64_t display_id,
1250 const Buffer& buffer) {
1251 auto* display = GetDisplay(display_id);
1252 if (display == nullptr) {
1253 cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
1254 return;
1255 }
1256
1257 buffer_handle_t imported_buffer = nullptr;
1258 auto buf_releaser = composer_resources_->CreateResourceReleaser(true);
1259
1260 auto error = composer_resources_->GetDisplayOutputBuffer(display_id, buffer,
1261 &imported_buffer,
1262 buf_releaser.get());
1263 if (error != hwc3::Error::kNone) {
1264 cmd_result_writer_->AddError(error);
1265 return;
1266 }
1267
1268 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
1269 auto fence = const_cast<::ndk::ScopedFileDescriptor&>(buffer.fence).release();
1270 error = Hwc2toHwc3Error(display->SetOutputBuffer(imported_buffer, fence));
1271 if (error != hwc3::Error::kNone) {
1272 cmd_result_writer_->AddError(error);
1273 return;
1274 }
1275}
1276void ComposerClient::ExecuteValidateDisplay(
1277 int64_t display_id,
1278 std::optional<ClockMonotonicTimestamp> /*expected_present_time*/
1279) {
1280 auto* display = GetDisplay(display_id);
1281 if (display == nullptr) {
1282 cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
1283 return;
1284 }
1285
1286 /* TODO: Handle expectedPresentTime */
Normunds Rieksts42820952024-03-12 15:42:06 +00001287 /* This can be implemented in multiple ways. For example, the expected present
1288 * time property can be implemented by the DRM driver directly as a CRTC
1289 * property. See:
1290 * https://cs.android.com/android/platform/superproject/main/+/b8b3b1646e64d0235f77b9e717a3e4082e26f2a8:hardware/google/graphics/common/libhwc2.1/libdrmresource/drm/drmcrtc.cpp;drc=468f6172546ab98983de18210222f231f16b21e1;l=88
1291 * Unfortunately there doesn't seem to be a standardised way of delaying
1292 * presentation with a timestamp in the DRM API. What we can do alternatively
1293 * is to spawn a separate presentation thread that could handle the VBlank
1294 * events by using DRM_MODE_PAGE_FLIP_EVENT and schedule them appropriately.
1295 */
Drew Davenport5951b112024-08-05 09:44:27 -06001296
1297 std::vector<int64_t> changed_layers;
1298 std::vector<Composition> composition_types;
1299 int32_t display_request_mask = 0;
1300 std::vector<int64_t> requested_layers;
1301 std::vector<int32_t> request_masks;
1302
1303 const hwc3::Error error = ValidateDisplayInternal(*display, &changed_layers,
1304 &composition_types,
1305 &display_request_mask,
1306 &requested_layers,
1307 &request_masks, nullptr,
1308 nullptr);
1309
1310 if (error != hwc3::Error::kNone) {
1311 cmd_result_writer_->AddError(error);
1312 }
1313
1314 // If a CommandError has been been set for the current DisplayCommand, then
1315 // no other results should be returned besides the error.
1316 if (cmd_result_writer_->HasError()) {
1317 return;
1318 }
1319
1320 DisplayChanges changes{};
1321 for (size_t i = 0; i < composition_types.size(); i++) {
1322 changes.AddLayerCompositionChange(display_id, changed_layers[i],
1323 composition_types[i]);
1324 }
1325
1326 std::vector<DisplayRequest::LayerRequest> layer_requests;
1327 for (size_t i = 0; i < requested_layers.size(); i++) {
1328 layer_requests.push_back({requested_layers[i], request_masks[i]});
1329 }
1330
1331 const DisplayRequest request_changes{display_id, display_request_mask,
1332 layer_requests};
1333 changes.display_request_changes = request_changes;
1334
1335 cmd_result_writer_->AddChanges(changes);
1336 composer_resources_->SetDisplayMustValidateState(display_id, false);
1337}
1338
1339void ComposerClient::ExecuteAcceptDisplayChanges(int64_t display_id) {
1340 auto* display = GetDisplay(display_id);
1341 if (display == nullptr) {
1342 cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
1343 return;
1344 }
1345
1346 auto error = Hwc2toHwc3Error(display->AcceptDisplayChanges());
1347 if (error != hwc3::Error::kNone) {
1348 cmd_result_writer_->AddError(error);
1349 return;
1350 }
1351}
1352
1353void ComposerClient::ExecutePresentDisplay(int64_t display_id) {
1354 auto* display = GetDisplay(display_id);
1355 if (display == nullptr) {
1356 cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
1357 return;
1358 }
1359
1360 ::android::base::unique_fd display_fence;
1361 std::unordered_map<int64_t, ::android::base::unique_fd> release_fences;
1362 auto error = PresentDisplayInternal(display_id, display_fence,
1363 release_fences);
1364 if (error != hwc3::Error::kNone) {
1365 cmd_result_writer_->AddError(error);
1366 }
1367 if (cmd_result_writer_->HasError()) {
1368 return;
1369 }
1370
1371 cmd_result_writer_->AddPresentFence(display_id, std::move(display_fence));
1372 cmd_result_writer_->AddReleaseFence(display_id, release_fences);
1373}
1374
1375void ComposerClient::ExecutePresentOrValidateDisplay(
1376 int64_t display_id,
1377 std::optional<ClockMonotonicTimestamp> expected_present_time) {
1378 auto* display = GetDisplay(display_id);
1379 if (display == nullptr) {
1380 cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
1381 return;
1382 }
1383
1384 /* TODO: Handle expectedPresentTime */
Normunds Rieksts42820952024-03-12 15:42:06 +00001385 /* This can be implemented in multiple ways. For example, the expected present
1386 * time property can be implemented by the DRM driver directly as a CRTC
1387 * property. See:
1388 * https://cs.android.com/android/platform/superproject/main/+/b8b3b1646e64d0235f77b9e717a3e4082e26f2a8:hardware/google/graphics/common/libhwc2.1/libdrmresource/drm/drmcrtc.cpp;drc=468f6172546ab98983de18210222f231f16b21e1;l=88
1389 * Unfortunately there doesn't seem to be a standardised way of delaying
1390 * presentation with a timestamp in the DRM API. What we can do alternatively
1391 * is to spawn a separate presentation thread that could handle the VBlank
1392 * events by using DRM_MODE_PAGE_FLIP_EVENT and schedule them appropriately.
1393 */
1394
Drew Davenport5951b112024-08-05 09:44:27 -06001395 /* TODO: Add check if it's possible to skip display validation */
1396 ExecuteValidateDisplay(display_id, expected_present_time);
1397 cmd_result_writer_
1398 ->AddPresentOrValidateResult(display_id,
1399 PresentOrValidate::Result::Validated);
1400}
1401
Dennis Tsiang33f0ece2023-11-29 12:45:04 +00001402} // namespace aidl::android::hardware::graphics::composer3::impl