blob: 902d612dd1d53a482ebe5a4955b4cf0c7f58f86a [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 Davenport5951b112024-08-05 09:44:27 -060088} // namespace
89
90ComposerClient::ComposerClient() {
91 DEBUG_FUNC();
92}
93
94bool ComposerClient::Init() {
95 DEBUG_FUNC();
96 composer_resources_ = ComposerResources::Create();
97 if (composer_resources_) {
98 hwc_ = std::make_unique<DrmHwcThree>(composer_resources_.get());
99 }
100 return composer_resources_ != nullptr;
101}
102
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000103ComposerClient::~ComposerClient() {
104 DEBUG_FUNC();
Drew Davenport1ac3b622024-09-05 10:59:16 -0600105 {
106 // First Deinit the displays to start shutting down the Display's dependent
107 // threads such as VSyncWorker.
108 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
109 hwc_->DeinitDisplays();
110 }
111 // Sleep to wait for threads to complete and exit.
112 const int time_for_threads_to_exit_us = 200000;
113 usleep(time_for_threads_to_exit_us);
114 {
115 // Hold the lock while destructing the hwc_ and the objects that it owns.
116 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
117 hwc_.reset();
118 }
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000119 LOG(DEBUG) << "removed composer client";
120}
121
Drew Davenport5951b112024-08-05 09:44:27 -0600122ndk::ScopedAStatus ComposerClient::createLayer(int64_t display_id,
123 int32_t buffer_slot_count,
124 int64_t* layer_id) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000125 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600126 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
127
128 HwcDisplay* display = GetDisplay(display_id);
129 if (display == nullptr) {
130 return ToBinderStatus(hwc3::Error::kBadDisplay);
131 }
132
133 hwc2_layer_t hwc2_layer_id = 0;
134 auto err = Hwc2toHwc3Error(display->CreateLayer(&hwc2_layer_id));
135 if (err != hwc3::Error::kNone) {
136 return ToBinderStatus(err);
137 }
138
139 const int64_t created_layer_id = Hwc2LayerToHwc3(hwc2_layer_id);
140 err = composer_resources_->AddLayer(display_id, created_layer_id,
141 buffer_slot_count);
142 if (err != hwc3::Error::kNone) {
143 destroyLayer(display_id, created_layer_id);
144 return ToBinderStatus(err);
145 }
146
147 *layer_id = created_layer_id;
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000148 return ndk::ScopedAStatus::ok();
149}
150
151ndk::ScopedAStatus ComposerClient::createVirtualDisplay(
Drew Davenport5951b112024-08-05 09:44:27 -0600152 int32_t width, int32_t height, AidlPixelFormat format_hint,
153 int32_t output_buffer_slot_count, VirtualDisplay* out_display) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000154 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600155 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
156
157 hwc2_display_t hwc2_display_id = 0;
158 // TODO: Format is currently not used in drm_hwcomposer.
159 int32_t hwc2_format = 0;
160 auto err = Hwc2toHwc3Error(hwc_->CreateVirtualDisplay(width, height,
161 &hwc2_format,
162 &hwc2_display_id));
163 if (err != hwc3::Error::kNone) {
164 return ToBinderStatus(err);
165 }
166
167 const int64_t created_display_id = Hwc2DisplayToHwc3(hwc2_display_id);
168 err = composer_resources_->AddVirtualDisplay(hwc2_display_id,
169 output_buffer_slot_count);
170 if (err != hwc3::Error::kNone) {
171 hwc_->DestroyVirtualDisplay(hwc2_display_id);
172 return ToBinderStatus(err);
173 }
174
175 out_display->display = created_display_id;
176 out_display->format = format_hint;
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000177 return ndk::ScopedAStatus::ok();
178}
179
Drew Davenport5951b112024-08-05 09:44:27 -0600180ndk::ScopedAStatus ComposerClient::destroyLayer(int64_t display_id,
181 int64_t layer_id) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000182 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600183 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
184 HwcDisplay* display = GetDisplay(display_id);
185 if (display == nullptr) {
186 return ToBinderStatus(hwc3::Error::kBadDisplay);
187 }
188
189 auto err = Hwc2toHwc3Error(display->DestroyLayer(Hwc3LayerToHwc2(layer_id)));
190 if (err != hwc3::Error::kNone) {
191 return ToBinderStatus(err);
192 }
193
194 err = composer_resources_->RemoveLayer(display_id, layer_id);
195 return ToBinderStatus(err);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000196}
197
Drew Davenport5951b112024-08-05 09:44:27 -0600198ndk::ScopedAStatus ComposerClient::destroyVirtualDisplay(int64_t display_id) {
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 auto err = Hwc2toHwc3Error(hwc_->DestroyVirtualDisplay(display_id));
202 return ToBinderStatus(err);
203}
204
205hwc3::Error ComposerClient::ValidateDisplayInternal(
206 HwcDisplay& display, std::vector<int64_t>* out_changed_layers,
207 std::vector<Composition>* out_composition_types,
208 int32_t* out_display_request_mask,
209 std::vector<int64_t>* out_requested_layers,
210 std::vector<int32_t>* out_request_masks,
211 ClientTargetProperty* /*out_client_target_property*/,
212 DimmingStage* /*out_dimming_stage*/) {
213 DEBUG_FUNC();
214
215 uint32_t num_types = 0;
216 uint32_t num_requests = 0;
217 const HWC2::Error hwc2_error = display.ValidateDisplay(&num_types,
218 &num_requests);
219
220 /* Check if display has pending changes and no errors */
221 if (hwc2_error != HWC2::Error::None &&
222 hwc2_error != HWC2::Error::HasChanges) {
223 return Hwc2toHwc3Error(hwc2_error);
224 }
225
Drew Davenport3f4469f2024-10-03 10:01:51 -0600226 hwc3::Error error = Hwc2toHwc3Error(
227 display.GetChangedCompositionTypes(&num_types, nullptr, nullptr));
228 if (error != hwc3::Error::kNone) {
229 return error;
230 }
231
Drew Davenport5951b112024-08-05 09:44:27 -0600232 std::vector<hwc2_layer_t> hwc_changed_layers(num_types);
233 std::vector<int32_t> hwc_composition_types(num_types);
Drew Davenport3f4469f2024-10-03 10:01:51 -0600234 error = Hwc2toHwc3Error(
Drew Davenport5951b112024-08-05 09:44:27 -0600235 display.GetChangedCompositionTypes(&num_types, hwc_changed_layers.data(),
236 hwc_composition_types.data()));
237 if (error != hwc3::Error::kNone) {
238 return error;
239 }
240
241 int32_t display_reqs = 0;
242 out_request_masks->resize(num_requests);
243 std::vector<hwc2_layer_t> hwc_requested_layers(num_requests);
244 error = Hwc2toHwc3Error(
245 display.GetDisplayRequests(&display_reqs, &num_requests,
246 hwc_requested_layers.data(),
247 out_request_masks->data()));
248 if (error != hwc3::Error::kNone) {
249 return error;
250 }
251
252 for (const auto& layer : hwc_changed_layers) {
253 out_changed_layers->emplace_back(Hwc2LayerToHwc3(layer));
254 }
255 for (const auto& type : hwc_composition_types) {
256 out_composition_types->emplace_back(Hwc2CompositionTypeToHwc3(type));
257 }
258 for (const auto& layer : hwc_requested_layers) {
259 out_requested_layers->emplace_back(Hwc2LayerToHwc3(layer));
260 }
261 *out_display_request_mask = display_reqs;
262
263 /* Client target property/dimming stage unsupported */
264 return hwc3::Error::kNone;
265}
266
267hwc3::Error ComposerClient::PresentDisplayInternal(
268 uint64_t display_id, ::android::base::unique_fd& out_display_fence,
269 std::unordered_map<int64_t, ::android::base::unique_fd>&
270 out_release_fences) {
271 DEBUG_FUNC();
272 auto* display = GetDisplay(display_id);
273 if (display == nullptr) {
274 return hwc3::Error::kBadDisplay;
275 }
276
277 if (composer_resources_->MustValidateDisplay(display_id)) {
278 return hwc3::Error::kNotValidated;
279 }
280
281 int32_t present_fence = -1;
282 auto error = Hwc2toHwc3Error(display->PresentDisplay(&present_fence));
283 if (error != hwc3::Error::kNone) {
284 return error;
285 }
286 out_display_fence.reset(present_fence);
287
288 uint32_t release_fence_count = 0;
289 error = Hwc2toHwc3Error(
290 display->GetReleaseFences(&release_fence_count, nullptr, nullptr));
291 if (error != hwc3::Error::kNone) {
292 return error;
293 }
294
295 std::vector<hwc2_layer_t> hwc_layers(release_fence_count);
296 std::vector<int32_t> hwc_fences(release_fence_count);
297 error = Hwc2toHwc3Error(display->GetReleaseFences(&release_fence_count,
298 hwc_layers.data(),
299 hwc_fences.data()));
300 if (error != hwc3::Error::kNone) {
301 return error;
302 }
303
304 for (size_t i = 0; i < hwc_layers.size(); i++) {
305 auto layer = Hwc2LayerToHwc3(hwc_layers[i]);
306 out_release_fences[layer] = ::android::base::unique_fd{hwc_fences[i]};
307 }
308
309 return hwc3::Error::kNone;
310}
311
312::android::HwcDisplay* ComposerClient::GetDisplay(uint64_t display_id) {
313 return hwc_->GetDisplay(display_id);
314}
315
316void ComposerClient::DispatchLayerCommand(int64_t display_id,
317 const LayerCommand& command) {
318 auto* display = GetDisplay(display_id);
319 if (display == nullptr) {
320 cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
321 return;
322 }
323
324 auto* layer = display->get_layer(command.layer);
325 if (layer == nullptr) {
326 cmd_result_writer_->AddError(hwc3::Error::kBadLayer);
327 return;
328 }
329
330 HwcLayerWrapper layer_wrapper{command.layer, layer};
331 if (command.buffer) {
332 ExecuteSetLayerBuffer(display_id, layer_wrapper, *command.buffer);
333 }
Drew Davenporta241a772024-09-24 11:26:30 -0600334 HwcLayer::LayerProperties properties;
335 properties.blend_mode = AidlToBlendMode(command.blendMode);
336 layer->SetLayerProperties(properties);
337
Drew Davenport5951b112024-08-05 09:44:27 -0600338 if (command.composition) {
339 ExecuteSetLayerComposition(display_id, layer_wrapper, *command.composition);
340 }
341 if (command.dataspace) {
342 ExecuteSetLayerDataspace(display_id, layer_wrapper, *command.dataspace);
343 }
344 if (command.displayFrame) {
345 ExecuteSetLayerDisplayFrame(display_id, layer_wrapper,
346 *command.displayFrame);
347 }
348 if (command.planeAlpha) {
349 ExecuteSetLayerPlaneAlpha(display_id, layer_wrapper, *command.planeAlpha);
350 }
351 if (command.sourceCrop) {
352 ExecuteSetLayerSourceCrop(display_id, layer_wrapper, *command.sourceCrop);
353 }
354 if (command.transform) {
355 ExecuteSetLayerTransform(display_id, layer_wrapper, *command.transform);
356 }
357 if (command.z) {
358 ExecuteSetLayerZOrder(display_id, layer_wrapper, *command.z);
359 }
360 if (command.brightness) {
361 ExecuteSetLayerBrightness(display_id, layer_wrapper, *command.brightness);
362 }
363
364 // Some unsupported functionality returns kUnsupported, and others
365 // are just a no-op.
366 // TODO: Audit whether some of these should actually return kUnsupported
367 // instead.
368 if (command.sidebandStream) {
369 cmd_result_writer_->AddError(hwc3::Error::kUnsupported);
370 }
371 // TODO: Blocking region handling missing.
372 // TODO: Layer surface damage.
373 // TODO: Layer visible region.
374 // TODO: Per-frame metadata.
375 // TODO: Layer color transform.
376 // TODO: Layer cursor position.
377 // TODO: Layer color.
378}
379
380void ComposerClient::ExecuteDisplayCommand(const DisplayCommand& command) {
381 const int64_t display_id = command.display;
382 if (hwc_->GetDisplay(display_id) == nullptr) {
383 cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
384 return;
385 }
386
387 for (const auto& layer_cmd : command.layers) {
388 DispatchLayerCommand(command.display, layer_cmd);
389 }
390
391 if (command.brightness) {
392 ExecuteSetDisplayBrightness(command.display, *command.brightness);
393 }
394 if (command.colorTransformMatrix) {
395 ExecuteSetDisplayColorTransform(command.display,
396 *command.colorTransformMatrix);
397 }
398 if (command.clientTarget) {
399 ExecuteSetDisplayClientTarget(command.display, *command.clientTarget);
400 }
401 if (command.virtualDisplayOutputBuffer) {
402 ExecuteSetDisplayOutputBuffer(command.display,
403 *command.virtualDisplayOutputBuffer);
404 }
405 if (command.validateDisplay) {
406 ExecuteValidateDisplay(command.display, command.expectedPresentTime);
407 }
408 if (command.acceptDisplayChanges) {
409 ExecuteAcceptDisplayChanges(command.display);
410 }
411 if (command.presentDisplay) {
412 ExecutePresentDisplay(command.display);
413 }
414 if (command.presentOrValidateDisplay) {
415 ExecutePresentOrValidateDisplay(command.display,
416 command.expectedPresentTime);
417 }
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000418}
419
420ndk::ScopedAStatus ComposerClient::executeCommands(
Drew Davenport5951b112024-08-05 09:44:27 -0600421 const std::vector<DisplayCommand>& commands,
422 std::vector<CommandResultPayload>* results) {
Drew Davenport49965852024-09-05 10:59:40 -0600423 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
424 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600425 cmd_result_writer_ = std::make_unique<CommandResultWriter>(results);
426 for (const auto& cmd : commands) {
427 ExecuteDisplayCommand(cmd);
428 cmd_result_writer_->IncrementCommand();
429 }
430 cmd_result_writer_.reset();
431
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000432 return ndk::ScopedAStatus::ok();
433}
434
Drew Davenport5951b112024-08-05 09:44:27 -0600435ndk::ScopedAStatus ComposerClient::getActiveConfig(int64_t display_id,
436 int32_t* config) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000437 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600438 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
439 HwcDisplay* display = GetDisplay(display_id);
440 if (display == nullptr) {
441 return ToBinderStatus(hwc3::Error::kBadDisplay);
442 }
443
444 uint32_t hwc2_config = 0;
445 const hwc3::Error error = Hwc2toHwc3Error(
446 display->GetActiveConfig(&hwc2_config));
447 if (error != hwc3::Error::kNone) {
448 return ToBinderStatus(error);
449 }
450 *config = Hwc2ConfigIdToHwc3(hwc2_config);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000451 return ndk::ScopedAStatus::ok();
452}
453
454ndk::ScopedAStatus ComposerClient::getColorModes(
Drew Davenport5951b112024-08-05 09:44:27 -0600455 int64_t display_id, std::vector<ColorMode>* color_modes) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000456 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600457 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
458 HwcDisplay* display = GetDisplay(display_id);
459 if (display == nullptr) {
460 return ToBinderStatus(hwc3::Error::kBadDisplay);
461 }
462
463 uint32_t num_modes = 0;
464 auto error = Hwc2toHwc3Error(display->GetColorModes(&num_modes, nullptr));
465 if (error != hwc3::Error::kNone) {
466 return ToBinderStatus(error);
467 }
468
469 std::vector<int32_t> hwc2_color_modes(num_modes);
470 error = Hwc2toHwc3Error(
471 display->GetColorModes(&num_modes, hwc2_color_modes.data()));
472 if (error != hwc3::Error::kNone) {
473 return ToBinderStatus(error);
474 }
475
476 for (const auto& mode : hwc2_color_modes) {
477 color_modes->push_back(Hwc2ColorModeToHwc3(mode));
478 }
479
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000480 return ndk::ScopedAStatus::ok();
481}
482
483ndk::ScopedAStatus ComposerClient::getDataspaceSaturationMatrix(
Drew Davenport5951b112024-08-05 09:44:27 -0600484 common::Dataspace dataspace, std::vector<float>* matrix) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000485 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600486 if (dataspace != common::Dataspace::SRGB_LINEAR) {
487 return ToBinderStatus(hwc3::Error::kBadParameter);
488 }
489
490 matrix->clear();
491 matrix->insert(matrix->begin(), kIdentityMatrix.begin(),
492 kIdentityMatrix.end());
493
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000494 return ndk::ScopedAStatus::ok();
495}
496
497ndk::ScopedAStatus ComposerClient::getDisplayAttribute(
Drew Davenport5951b112024-08-05 09:44:27 -0600498 int64_t display_id, int32_t config, DisplayAttribute attribute,
499 int32_t* value) {
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 const hwc3::Error error = Hwc2toHwc3Error(
508 display->GetDisplayAttribute(Hwc3ConfigIdToHwc2(config),
509 Hwc3DisplayAttributeToHwc2(attribute),
510 value));
511 return ToBinderStatus(error);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000512}
513
514ndk::ScopedAStatus ComposerClient::getDisplayCapabilities(
Drew Davenport5951b112024-08-05 09:44:27 -0600515 int64_t display_id, std::vector<DisplayCapability>* caps) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000516 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600517 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
518 HwcDisplay* display = GetDisplay(display_id);
519 if (display == nullptr) {
520 return ToBinderStatus(hwc3::Error::kBadDisplay);
521 }
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000522
Drew Davenport5951b112024-08-05 09:44:27 -0600523 uint32_t num_capabilities = 0;
524 hwc3::Error error = Hwc2toHwc3Error(
525 display->GetDisplayCapabilities(&num_capabilities, nullptr));
526 if (error != hwc3::Error::kNone) {
527 return ToBinderStatus(error);
528 }
529
530 std::vector<uint32_t> out_caps(num_capabilities);
531 error = Hwc2toHwc3Error(
532 display->GetDisplayCapabilities(&num_capabilities, out_caps.data()));
533 if (error != hwc3::Error::kNone) {
534 return ToBinderStatus(error);
535 }
536
537 caps->reserve(num_capabilities);
538 for (const auto cap : out_caps) {
539 caps->emplace_back(Hwc2DisplayCapabilityToHwc3(cap));
540 }
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000541 return ndk::ScopedAStatus::ok();
542}
543
544ndk::ScopedAStatus ComposerClient::getDisplayConfigs(
Drew Davenport5951b112024-08-05 09:44:27 -0600545 int64_t display_id, std::vector<int32_t>* configs) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000546 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600547 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
548 HwcDisplay* display = GetDisplay(display_id);
549 if (display == nullptr) {
550 return ToBinderStatus(hwc3::Error::kBadDisplay);
551 }
552
553 uint32_t num_configs = 0;
554 hwc3::Error error = Hwc2toHwc3Error(
Drew Davenportf7e88332024-09-06 12:54:38 -0600555 display->LegacyGetDisplayConfigs(&num_configs, nullptr));
Drew Davenport5951b112024-08-05 09:44:27 -0600556 if (error != hwc3::Error::kNone) {
557 return ToBinderStatus(error);
558 }
559
560 std::vector<hwc2_config_t> out_configs(num_configs);
561 error = Hwc2toHwc3Error(
Drew Davenportf7e88332024-09-06 12:54:38 -0600562 display->LegacyGetDisplayConfigs(&num_configs, out_configs.data()));
Drew Davenport5951b112024-08-05 09:44:27 -0600563 if (error != hwc3::Error::kNone) {
564 return ToBinderStatus(error);
565 }
566
567 configs->reserve(num_configs);
568 for (const auto config : out_configs) {
569 configs->emplace_back(Hwc2ConfigIdToHwc3(config));
570 }
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000571 return ndk::ScopedAStatus::ok();
572}
573
574ndk::ScopedAStatus ComposerClient::getDisplayConnectionType(
Drew Davenport5951b112024-08-05 09:44:27 -0600575 int64_t display_id, DisplayConnectionType* type) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000576 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600577 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
578 HwcDisplay* display = GetDisplay(display_id);
579 if (display == nullptr) {
580 return ToBinderStatus(hwc3::Error::kBadDisplay);
581 }
582
583 uint32_t out_type = 0;
584 const hwc3::Error error = Hwc2toHwc3Error(
585 display->GetDisplayConnectionType(&out_type));
586 if (error != hwc3::Error::kNone) {
587 return ToBinderStatus(error);
588 }
589
590 *type = Hwc2DisplayConnectionTypeToHwc3(out_type);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000591 return ndk::ScopedAStatus::ok();
592}
593
594ndk::ScopedAStatus ComposerClient::getDisplayIdentificationData(
Drew Davenport5951b112024-08-05 09:44:27 -0600595 int64_t display_id, DisplayIdentification* id) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000596 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600597 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
598 HwcDisplay* display = GetDisplay(display_id);
599 if (display == nullptr) {
600 return ToBinderStatus(hwc3::Error::kBadDisplay);
601 }
602
603 uint8_t port = 0;
604 uint32_t data_size = 0;
605 hwc3::Error error = Hwc2toHwc3Error(
606 display->GetDisplayIdentificationData(&port, &data_size, nullptr));
607 if (error != hwc3::Error::kNone) {
608 return ToBinderStatus(error);
609 }
610
611 id->data.resize(data_size);
612 error = Hwc2toHwc3Error(
613 display->GetDisplayIdentificationData(&port, &data_size,
614 id->data.data()));
615 if (error != hwc3::Error::kNone) {
616 return ToBinderStatus(error);
617 }
618
619 id->port = static_cast<int8_t>(port);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000620 return ndk::ScopedAStatus::ok();
621}
622
Drew Davenport5951b112024-08-05 09:44:27 -0600623ndk::ScopedAStatus ComposerClient::getDisplayName(int64_t display_id,
624 std::string* name) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000625 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600626 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
627 HwcDisplay* display = GetDisplay(display_id);
628 if (display == nullptr) {
629 return ToBinderStatus(hwc3::Error::kBadDisplay);
630 }
631
632 uint32_t size = 0;
633 auto error = Hwc2toHwc3Error(display->GetDisplayName(&size, nullptr));
634 if (error != hwc3::Error::kNone) {
635 return ToBinderStatus(error);
636 }
637
638 name->resize(size);
639 error = Hwc2toHwc3Error(display->GetDisplayName(&size, name->data()));
640 return ToBinderStatus(error);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000641}
642
643ndk::ScopedAStatus ComposerClient::getDisplayVsyncPeriod(
Drew Davenport5951b112024-08-05 09:44:27 -0600644 int64_t display_id, int32_t* vsync_period) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000645 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600646 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
647 HwcDisplay* display = GetDisplay(display_id);
648 if (display == nullptr) {
649 return ToBinderStatus(hwc3::Error::kBadDisplay);
650 }
651
652 uint32_t hwc2_vsync_period = 0;
653 auto error = Hwc2toHwc3Error(
654 display->GetDisplayVsyncPeriod(&hwc2_vsync_period));
655 if (error != hwc3::Error::kNone) {
656 return ToBinderStatus(error);
657 }
658
659 *vsync_period = static_cast<int32_t>(hwc2_vsync_period);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000660 return ndk::ScopedAStatus::ok();
661}
662
663ndk::ScopedAStatus ComposerClient::getDisplayedContentSample(
Drew Davenport5951b112024-08-05 09:44:27 -0600664 int64_t /*display_id*/, int64_t /*max_frames*/, int64_t /*timestamp*/,
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000665 DisplayContentSample* /*samples*/) {
666 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600667 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000668}
669
670ndk::ScopedAStatus ComposerClient::getDisplayedContentSamplingAttributes(
Drew Davenport5951b112024-08-05 09:44:27 -0600671 int64_t /*display_id*/, DisplayContentSamplingAttributes* /*attrs*/) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000672 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600673 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000674}
675
676ndk::ScopedAStatus ComposerClient::getDisplayPhysicalOrientation(
Drew Davenport5951b112024-08-05 09:44:27 -0600677 int64_t display_id, common::Transform* orientation) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000678 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600679 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
680 HwcDisplay* display = GetDisplay(display_id);
681 if (display == nullptr) {
682 return ToBinderStatus(hwc3::Error::kBadDisplay);
683 }
684
685 *orientation = common::Transform::NONE;
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000686 return ndk::ScopedAStatus::ok();
687}
688
Drew Davenport5951b112024-08-05 09:44:27 -0600689ndk::ScopedAStatus ComposerClient::getHdrCapabilities(int64_t display_id,
690 HdrCapabilities* caps) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000691 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600692 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
693 HwcDisplay* display = GetDisplay(display_id);
694 if (display == nullptr) {
695 return ToBinderStatus(hwc3::Error::kBadDisplay);
696 }
697
698 /* No HDR capabilities */
699 caps->types.clear();
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000700 return ndk::ScopedAStatus::ok();
701}
702
Drew Davenport5951b112024-08-05 09:44:27 -0600703ndk::ScopedAStatus ComposerClient::getMaxVirtualDisplayCount(int32_t* count) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000704 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600705 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
706 *count = static_cast<int32_t>(hwc_->GetMaxVirtualDisplayCount());
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000707 return ndk::ScopedAStatus::ok();
708}
709
710ndk::ScopedAStatus ComposerClient::getPerFrameMetadataKeys(
Drew Davenport5951b112024-08-05 09:44:27 -0600711 int64_t /*display_id*/, std::vector<PerFrameMetadataKey>* /*keys*/) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000712 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600713 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000714}
715
716ndk::ScopedAStatus ComposerClient::getReadbackBufferAttributes(
Drew Davenport5951b112024-08-05 09:44:27 -0600717 int64_t /*display_id*/, ReadbackBufferAttributes* /*attrs*/) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000718 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600719 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000720}
721
722ndk::ScopedAStatus ComposerClient::getReadbackBufferFence(
Drew Davenport5951b112024-08-05 09:44:27 -0600723 int64_t /*display_id*/, ndk::ScopedFileDescriptor* /*acquireFence*/) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000724 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600725 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000726}
727
728ndk::ScopedAStatus ComposerClient::getRenderIntents(
Drew Davenport5951b112024-08-05 09:44:27 -0600729 int64_t display_id, ColorMode mode, std::vector<RenderIntent>* intents) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000730 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600731 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
732 HwcDisplay* display = GetDisplay(display_id);
733 if (display == nullptr) {
734 return ToBinderStatus(hwc3::Error::kBadDisplay);
735 }
736
737 const int32_t hwc2_color_mode = Hwc3ColorModeToHwc2(mode);
738 uint32_t out_num_intents = 0;
739 auto error = Hwc2toHwc3Error(
740 display->GetRenderIntents(hwc2_color_mode, &out_num_intents, nullptr));
741 if (error != hwc3::Error::kNone) {
742 return ToBinderStatus(error);
743 }
744
745 std::vector<int32_t> out_intents(out_num_intents);
746 error = Hwc2toHwc3Error(display->GetRenderIntents(hwc2_color_mode,
747 &out_num_intents,
748 out_intents.data()));
749 if (error != hwc3::Error::kNone) {
750 return ToBinderStatus(error);
751 }
752
753 intents->reserve(out_num_intents);
754 for (const auto intent : out_intents) {
755 intents->emplace_back(Hwc2RenderIntentToHwc3(intent));
756 }
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000757 return ndk::ScopedAStatus::ok();
758}
759
760ndk::ScopedAStatus ComposerClient::getSupportedContentTypes(
Drew Davenport5951b112024-08-05 09:44:27 -0600761 int64_t display_id, std::vector<ContentType>* types) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000762 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600763 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
764 HwcDisplay* display = GetDisplay(display_id);
765 if (display == nullptr) {
766 return ToBinderStatus(hwc3::Error::kBadDisplay);
767 }
768
Drew Davenport8d38dc72024-09-24 12:26:07 -0600769 // Support for ContentType is not implemented.
770 types->clear();
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000771 return ndk::ScopedAStatus::ok();
772}
773
774ndk::ScopedAStatus ComposerClient::getDisplayDecorationSupport(
Drew Davenport5951b112024-08-05 09:44:27 -0600775 int64_t /*display_id*/,
776 std::optional<common::DisplayDecorationSupport>* /*support_struct*/) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000777 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600778 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000779}
780
781ndk::ScopedAStatus ComposerClient::registerCallback(
Drew Davenport5951b112024-08-05 09:44:27 -0600782 const std::shared_ptr<IComposerCallback>& callback) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000783 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600784 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
785 // This function is specified to be called exactly once.
786 hwc_->Init(callback);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000787 return ndk::ScopedAStatus::ok();
788}
789
Drew Davenport5951b112024-08-05 09:44:27 -0600790ndk::ScopedAStatus ComposerClient::setActiveConfig(int64_t display_id,
791 int32_t config) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000792 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600793 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
794 HwcDisplay* display = GetDisplay(display_id);
795 if (display == nullptr) {
796 return ToBinderStatus(hwc3::Error::kBadDisplay);
797 }
798
799 return ToBinderStatus(Hwc2toHwc3Error(display->SetActiveConfig(config)));
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000800}
801
802ndk::ScopedAStatus ComposerClient::setActiveConfigWithConstraints(
Drew Davenport5951b112024-08-05 09:44:27 -0600803 int64_t display_id, int32_t config,
804 const VsyncPeriodChangeConstraints& constraints,
805 VsyncPeriodChangeTimeline* timeline) {
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
813 hwc_vsync_period_change_constraints_t hwc2_constraints;
814 hwc2_constraints.desiredTimeNanos = constraints.desiredTimeNanos;
815 hwc2_constraints.seamlessRequired = static_cast<uint8_t>(
816 constraints.seamlessRequired);
817
818 hwc_vsync_period_change_timeline_t hwc2_timeline{};
819 auto error = Hwc2toHwc3Error(
820 display->SetActiveConfigWithConstraints(config, &hwc2_constraints,
821 &hwc2_timeline));
822 if (error != hwc3::Error::kNone) {
823 return ToBinderStatus(error);
824 }
825
826 timeline->refreshTimeNanos = hwc2_timeline.refreshTimeNanos;
827 timeline->newVsyncAppliedTimeNanos = hwc2_timeline.newVsyncAppliedTimeNanos;
828 timeline->refreshRequired = static_cast<bool>(hwc2_timeline.refreshRequired);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000829 return ndk::ScopedAStatus::ok();
830}
831
Drew Davenport5951b112024-08-05 09:44:27 -0600832ndk::ScopedAStatus ComposerClient::setBootDisplayConfig(int64_t /*display_id*/,
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000833 int32_t /*config*/) {
834 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600835 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000836}
837
Drew Davenport5951b112024-08-05 09:44:27 -0600838ndk::ScopedAStatus ComposerClient::clearBootDisplayConfig(
839 int64_t /*display_id*/) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000840 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600841 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000842}
843
844ndk::ScopedAStatus ComposerClient::getPreferredBootDisplayConfig(
Drew Davenport5951b112024-08-05 09:44:27 -0600845 int64_t /*display_id*/, int32_t* /*config*/) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000846 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600847 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000848}
849
Drew Davenport5951b112024-08-05 09:44:27 -0600850ndk::ScopedAStatus ComposerClient::setAutoLowLatencyMode(int64_t display_id,
851 bool on) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000852 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600853 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
854 HwcDisplay* display = GetDisplay(display_id);
855 if (display == nullptr) {
856 return ToBinderStatus(hwc3::Error::kBadDisplay);
857 }
858
859 auto error = Hwc2toHwc3Error(display->SetAutoLowLatencyMode(on));
860 return ToBinderStatus(error);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000861}
862
Drew Davenport5951b112024-08-05 09:44:27 -0600863ndk::ScopedAStatus ComposerClient::setClientTargetSlotCount(int64_t display_id,
864 int32_t count) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000865 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600866 return ToBinderStatus(
867 composer_resources_->SetDisplayClientTargetCacheSize(display_id, count));
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000868}
869
Drew Davenport5951b112024-08-05 09:44:27 -0600870ndk::ScopedAStatus ComposerClient::setColorMode(int64_t display_id,
871 ColorMode mode,
872 RenderIntent intent) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000873 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600874 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
875 HwcDisplay* display = GetDisplay(display_id);
876 if (display == nullptr) {
877 return ToBinderStatus(hwc3::Error::kBadDisplay);
878 }
879
880 auto error = display->SetColorModeWithIntent(Hwc3ColorModeToHwc2(mode),
881 Hwc3RenderIntentToHwc2(intent));
882 return ToBinderStatus(Hwc2toHwc3Error(error));
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000883}
884
Drew Davenport5951b112024-08-05 09:44:27 -0600885ndk::ScopedAStatus ComposerClient::setContentType(int64_t display_id,
886 ContentType type) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000887 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600888 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
889 HwcDisplay* display = GetDisplay(display_id);
890 if (display == nullptr) {
891 return ToBinderStatus(hwc3::Error::kBadDisplay);
892 }
893
Drew Davenport8d38dc72024-09-24 12:26:07 -0600894 if (type == ContentType::NONE) {
895 return ndk::ScopedAStatus::ok();
896 }
897 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000898}
899
900ndk::ScopedAStatus ComposerClient::setDisplayedContentSamplingEnabled(
Drew Davenport5951b112024-08-05 09:44:27 -0600901 int64_t /*display_id*/, bool /*enable*/,
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000902 FormatColorComponent /*componentMask*/, int64_t /*maxFrames*/) {
903 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600904 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000905}
906
Drew Davenport5951b112024-08-05 09:44:27 -0600907ndk::ScopedAStatus ComposerClient::setPowerMode(int64_t display_id,
908 PowerMode mode) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000909 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600910 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
911 HwcDisplay* display = GetDisplay(display_id);
912 if (display == nullptr) {
913 return ToBinderStatus(hwc3::Error::kBadDisplay);
914 }
915
Dennis Tsiang1a966202024-01-24 12:46:33 +0000916 if (mode == PowerMode::ON_SUSPEND) {
917 return ToBinderStatus(hwc3::Error::kUnsupported);
918 }
919
Drew Davenport5951b112024-08-05 09:44:27 -0600920 auto error = display->SetPowerMode(Hwc3PowerModeToHwc2(mode));
921 return ToBinderStatus(Hwc2toHwc3Error(error));
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000922}
923
924ndk::ScopedAStatus ComposerClient::setReadbackBuffer(
Drew Davenport5951b112024-08-05 09:44:27 -0600925 int64_t /*display_id*/, const AidlNativeHandle& /*aidlBuffer*/,
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000926 const ndk::ScopedFileDescriptor& /*releaseFence*/) {
927 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600928 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000929}
930
Drew Davenport5951b112024-08-05 09:44:27 -0600931ndk::ScopedAStatus ComposerClient::setVsyncEnabled(int64_t display_id,
932 bool enabled) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000933 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600934 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
935 HwcDisplay* display = GetDisplay(display_id);
936 if (display == nullptr) {
937 return ToBinderStatus(hwc3::Error::kBadDisplay);
938 }
939
940 auto error = display->SetVsyncEnabled(static_cast<int32_t>(enabled));
941 return ToBinderStatus(Hwc2toHwc3Error(error));
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000942}
943
Drew Davenport5951b112024-08-05 09:44:27 -0600944ndk::ScopedAStatus ComposerClient::setIdleTimerEnabled(int64_t /*display_id*/,
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000945 int32_t /*timeout*/) {
946 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600947 return ToBinderStatus(hwc3::Error::kUnsupported);
948}
949
Drew Davenport7f1761b2024-08-20 10:09:43 -0600950ndk::ScopedAStatus ComposerClient::getOverlaySupport(
951 OverlayProperties* /*out_overlay_properties*/) {
952 return ToBinderStatus(hwc3::Error::kUnsupported);
953}
954
955ndk::ScopedAStatus ComposerClient::getHdrConversionCapabilities(
956 std::vector<common::HdrConversionCapability>* /*out_capabilities*/) {
957 return ToBinderStatus(hwc3::Error::kUnsupported);
958}
959
960ndk::ScopedAStatus ComposerClient::setHdrConversionStrategy(
961 const common::HdrConversionStrategy& /*conversion_strategy*/,
962 common::Hdr* /*out_hdr*/) {
963 return ToBinderStatus(hwc3::Error::kUnsupported);
964}
965
966ndk::ScopedAStatus ComposerClient::setRefreshRateChangedCallbackDebugEnabled(
967 int64_t /*display*/, bool /*enabled*/) {
968 return ToBinderStatus(hwc3::Error::kUnsupported);
969}
970
971ndk::ScopedAStatus ComposerClient::getDisplayConfigurations(
Drew Davenportf7e88332024-09-06 12:54:38 -0600972 int64_t display_id, int32_t /*max_frame_interval_ns*/,
Drew Davenport7f1761b2024-08-20 10:09:43 -0600973 std::vector<DisplayConfiguration>* configurations) {
Drew Davenportf7e88332024-09-06 12:54:38 -0600974 DEBUG_FUNC();
975 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
976 HwcDisplay* display = GetDisplay(display_id);
977 if (display == nullptr) {
978 return ToBinderStatus(hwc3::Error::kBadDisplay);
979 }
980
981 const HwcDisplayConfigs& configs = display->GetDisplayConfigs();
982 for (const auto& [id, config] : configs.hwc_configs) {
Drew Davenportf7e88332024-09-06 12:54:38 -0600983 configurations->emplace_back(
984 DisplayConfiguration{.configId = static_cast<int32_t>(config.id),
985 .width = config.mode.GetRawMode().hdisplay,
986 .height = config.mode.GetRawMode().vdisplay,
987 .configGroup = static_cast<int32_t>(
988 config.group_id),
Drew Davenport8053f2e2024-10-02 13:44:41 -0600989 .vsyncPeriod = config.mode.GetVSyncPeriodNs()});
Drew Davenportf7e88332024-09-06 12:54:38 -0600990
991 if (configs.mm_width != 0) {
992 // ideally this should be vdisplay/mm_heigth, however mm_height
993 // comes from edid parsing and is highly unreliable. Viewing the
994 // rarity of anisotropic displays, falling back to a single value
995 // for dpi yield more correct output.
996 static const float kMmPerInch = 25.4;
997 float dpi = float(config.mode.GetRawMode().hdisplay) * kMmPerInch /
998 float(configs.mm_width);
999 configurations->back().dpi = {.x = dpi, .y = dpi};
1000 }
1001
1002 // TODO: Populate vrrConfig.
1003 }
1004 return ndk::ScopedAStatus::ok();
Drew Davenport7f1761b2024-08-20 10:09:43 -06001005}
1006
1007ndk::ScopedAStatus ComposerClient::notifyExpectedPresent(
1008 int64_t /*display*/, const ClockMonotonicTimestamp& /*expected_present_time*/,
1009 int32_t /*frame_interval_ns*/) {
1010 return ToBinderStatus(hwc3::Error::kUnsupported);
1011}
1012
Drew Davenport5951b112024-08-05 09:44:27 -06001013std::string ComposerClient::Dump() {
1014 uint32_t size = 0;
1015 hwc_->Dump(&size, nullptr);
1016
1017 std::string buffer(size, '\0');
1018 hwc_->Dump(&size, &buffer.front());
1019 return buffer;
Dennis Tsiang33f0ece2023-11-29 12:45:04 +00001020}
1021
1022::ndk::SpAIBinder ComposerClient::createBinder() {
1023 auto binder = BnComposerClient::createBinder();
1024 AIBinder_setInheritRt(binder.get(), true);
1025 return binder;
1026}
1027
Drew Davenport5951b112024-08-05 09:44:27 -06001028void ComposerClient::ExecuteSetLayerBuffer(int64_t display_id,
1029 HwcLayerWrapper& layer,
1030 const Buffer& buffer) {
1031 buffer_handle_t imported_buffer = nullptr;
1032
1033 auto releaser = composer_resources_->CreateResourceReleaser(true);
1034 auto err = composer_resources_->GetLayerBuffer(display_id, layer.layer_id,
1035 buffer, &imported_buffer,
1036 releaser.get());
1037 if (err != hwc3::Error::kNone) {
1038 cmd_result_writer_->AddError(err);
1039 return;
1040 }
1041
1042 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
1043 auto fence_fd = const_cast<ndk::ScopedFileDescriptor&>(buffer.fence)
1044 .release();
1045 err = Hwc2toHwc3Error(layer.layer->SetLayerBuffer(imported_buffer, fence_fd));
1046 if (err != hwc3::Error::kNone) {
1047 cmd_result_writer_->AddError(err);
1048 }
1049}
1050
Drew Davenport5951b112024-08-05 09:44:27 -06001051void ComposerClient::ExecuteSetLayerComposition(
1052 int64_t /*display_id*/, HwcLayerWrapper& layer,
1053 const ParcelableComposition& composition) {
1054 hwc3::Error error = hwc3::Error::kNone;
1055 switch (composition.composition) {
1056 // Unsupported composition types should set an error for the current
1057 // DisplayCommand.
1058 case Composition::DISPLAY_DECORATION:
1059 case Composition::SIDEBAND:
1060 error = hwc3::Error::kUnsupported;
1061 break;
1062 default:
1063 error = Hwc2toHwc3Error(layer.layer->SetLayerCompositionType(
1064 Hwc3CompositionToHwc2(composition.composition)));
1065 }
1066 if (error != hwc3::Error::kNone) {
1067 cmd_result_writer_->AddError(error);
1068 }
1069}
1070
1071void ComposerClient::ExecuteSetLayerDataspace(
1072 int64_t /*display_id*/, HwcLayerWrapper& layer,
1073 const ParcelableDataspace& dataspace) {
1074 auto err = Hwc2toHwc3Error(
1075 layer.layer->SetLayerDataspace(Hwc3DataspaceToHwc2(dataspace.dataspace)));
1076 if (err != hwc3::Error::kNone) {
1077 cmd_result_writer_->AddError(err);
1078 }
1079}
1080
1081void ComposerClient::ExecuteSetLayerDisplayFrame(int64_t /*display_id*/,
1082 HwcLayerWrapper& layer,
1083 const common::Rect& rect) {
1084 const hwc_rect_t hwc2_rect{rect.left, rect.top, rect.right, rect.bottom};
1085 auto err = Hwc2toHwc3Error(layer.layer->SetLayerDisplayFrame(hwc2_rect));
1086 if (err != hwc3::Error::kNone) {
1087 cmd_result_writer_->AddError(err);
1088 }
1089}
1090void ComposerClient::ExecuteSetLayerPlaneAlpha(int64_t /*display_id*/,
1091 HwcLayerWrapper& layer,
1092 const PlaneAlpha& plane_alpha) {
1093 auto err = Hwc2toHwc3Error(
1094 layer.layer->SetLayerPlaneAlpha(plane_alpha.alpha));
1095 if (err != hwc3::Error::kNone) {
1096 cmd_result_writer_->AddError(err);
1097 }
1098}
1099
1100void ComposerClient::ExecuteSetLayerSourceCrop(
1101 int64_t /*display_id*/, HwcLayerWrapper& layer,
1102 const common::FRect& source_crop) {
1103 const hwc_frect_t rect{source_crop.left, source_crop.top, source_crop.right,
1104 source_crop.bottom};
1105 auto err = Hwc2toHwc3Error(layer.layer->SetLayerSourceCrop(rect));
1106 if (err != hwc3::Error::kNone) {
1107 cmd_result_writer_->AddError(err);
1108 }
1109}
1110void ComposerClient::ExecuteSetLayerTransform(
1111 int64_t /*display_id*/, HwcLayerWrapper& layer,
1112 const ParcelableTransform& transform) {
1113 auto err = Hwc2toHwc3Error(
1114 layer.layer->SetLayerTransform(Hwc3TransformToHwc2(transform.transform)));
1115 if (err != hwc3::Error::kNone) {
1116 cmd_result_writer_->AddError(err);
1117 }
1118}
1119void ComposerClient::ExecuteSetLayerZOrder(int64_t /*display_id*/,
1120 HwcLayerWrapper& layer,
1121 const ZOrder& z_order) {
1122 auto err = Hwc2toHwc3Error(layer.layer->SetLayerZOrder(z_order.z));
1123 if (err != hwc3::Error::kNone) {
1124 cmd_result_writer_->AddError(err);
1125 }
1126}
1127
1128void ComposerClient::ExecuteSetLayerBrightness(
1129 int64_t /*display_id*/, HwcLayerWrapper& /*layer*/,
1130 const LayerBrightness& brightness) {
1131 if (std::signbit(brightness.brightness) ||
1132 std::isnan(brightness.brightness)) {
1133 cmd_result_writer_->AddError(hwc3::Error::kBadParameter);
1134 }
1135}
1136
1137void ComposerClient::ExecuteSetDisplayBrightness(
1138 uint64_t display_id, const DisplayBrightness& command) {
1139 auto* display = GetDisplay(display_id);
1140 if (display == nullptr) {
1141 cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
1142 return;
1143 }
1144
1145 auto error = Hwc2toHwc3Error(
1146 display->SetDisplayBrightness(command.brightness));
1147 if (error != hwc3::Error::kNone) {
1148 cmd_result_writer_->AddError(error);
1149 }
1150}
1151void ComposerClient::ExecuteSetDisplayColorTransform(
1152 uint64_t display_id, const std::vector<float>& matrix) {
1153 auto* display = GetDisplay(display_id);
1154 if (display == nullptr) {
1155 cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
1156 return;
1157 }
1158
1159 auto almost_equal = [](auto a, auto b) {
1160 const float epsilon = 0.001F;
1161 return std::abs(a - b) < epsilon;
1162 };
1163 const bool is_identity = std::equal(matrix.begin(), matrix.end(),
1164 kIdentityMatrix.begin(), almost_equal);
1165
1166 const int32_t hint = is_identity ? HAL_COLOR_TRANSFORM_IDENTITY
1167 : HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX;
1168
1169 auto error = Hwc2toHwc3Error(display->SetColorTransform(matrix.data(), hint));
1170 if (error != hwc3::Error::kNone) {
1171 cmd_result_writer_->AddError(error);
1172 }
1173}
1174void ComposerClient::ExecuteSetDisplayClientTarget(
1175 uint64_t display_id, const ClientTarget& command) {
1176 auto* display = GetDisplay(display_id);
1177 if (display == nullptr) {
1178 cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
1179 return;
1180 }
1181
1182 hwc_region_t damage_regions;
1183 damage_regions.numRects = command.damage.size();
1184
1185 std::vector<hwc_rect_t> regions(command.damage.size());
1186 for (const auto& region : command.damage) {
1187 regions.push_back({region.left, region.top, region.right, region.bottom});
1188 }
1189 damage_regions.rects = regions.data();
1190
1191 buffer_handle_t imported_buffer = nullptr;
1192 auto buf_releaser = composer_resources_->CreateResourceReleaser(true);
1193
1194 auto error = composer_resources_->GetDisplayClientTarget(display_id,
1195 command.buffer,
1196 &imported_buffer,
1197 buf_releaser.get());
1198 if (error != hwc3::Error::kNone) {
1199 cmd_result_writer_->AddError(error);
1200 return;
1201 }
1202
1203 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
1204 auto fence = const_cast<::ndk::ScopedFileDescriptor&>(command.buffer.fence)
1205 .release();
1206 error = Hwc2toHwc3Error(
1207 display->SetClientTarget(imported_buffer, fence,
1208 Hwc3DataspaceToHwc2(command.dataspace),
1209 damage_regions));
1210 if (error != hwc3::Error::kNone) {
1211 cmd_result_writer_->AddError(error);
1212 }
1213}
1214
1215void ComposerClient::ExecuteSetDisplayOutputBuffer(uint64_t display_id,
1216 const Buffer& buffer) {
1217 auto* display = GetDisplay(display_id);
1218 if (display == nullptr) {
1219 cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
1220 return;
1221 }
1222
1223 buffer_handle_t imported_buffer = nullptr;
1224 auto buf_releaser = composer_resources_->CreateResourceReleaser(true);
1225
1226 auto error = composer_resources_->GetDisplayOutputBuffer(display_id, buffer,
1227 &imported_buffer,
1228 buf_releaser.get());
1229 if (error != hwc3::Error::kNone) {
1230 cmd_result_writer_->AddError(error);
1231 return;
1232 }
1233
1234 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
1235 auto fence = const_cast<::ndk::ScopedFileDescriptor&>(buffer.fence).release();
1236 error = Hwc2toHwc3Error(display->SetOutputBuffer(imported_buffer, fence));
1237 if (error != hwc3::Error::kNone) {
1238 cmd_result_writer_->AddError(error);
1239 return;
1240 }
1241}
1242void ComposerClient::ExecuteValidateDisplay(
1243 int64_t display_id,
1244 std::optional<ClockMonotonicTimestamp> /*expected_present_time*/
1245) {
1246 auto* display = GetDisplay(display_id);
1247 if (display == nullptr) {
1248 cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
1249 return;
1250 }
1251
1252 /* TODO: Handle expectedPresentTime */
Normunds Rieksts42820952024-03-12 15:42:06 +00001253 /* This can be implemented in multiple ways. For example, the expected present
1254 * time property can be implemented by the DRM driver directly as a CRTC
1255 * property. See:
1256 * https://cs.android.com/android/platform/superproject/main/+/b8b3b1646e64d0235f77b9e717a3e4082e26f2a8:hardware/google/graphics/common/libhwc2.1/libdrmresource/drm/drmcrtc.cpp;drc=468f6172546ab98983de18210222f231f16b21e1;l=88
1257 * Unfortunately there doesn't seem to be a standardised way of delaying
1258 * presentation with a timestamp in the DRM API. What we can do alternatively
1259 * is to spawn a separate presentation thread that could handle the VBlank
1260 * events by using DRM_MODE_PAGE_FLIP_EVENT and schedule them appropriately.
1261 */
Drew Davenport5951b112024-08-05 09:44:27 -06001262
1263 std::vector<int64_t> changed_layers;
1264 std::vector<Composition> composition_types;
1265 int32_t display_request_mask = 0;
1266 std::vector<int64_t> requested_layers;
1267 std::vector<int32_t> request_masks;
1268
1269 const hwc3::Error error = ValidateDisplayInternal(*display, &changed_layers,
1270 &composition_types,
1271 &display_request_mask,
1272 &requested_layers,
1273 &request_masks, nullptr,
1274 nullptr);
1275
1276 if (error != hwc3::Error::kNone) {
1277 cmd_result_writer_->AddError(error);
1278 }
1279
1280 // If a CommandError has been been set for the current DisplayCommand, then
1281 // no other results should be returned besides the error.
1282 if (cmd_result_writer_->HasError()) {
1283 return;
1284 }
1285
1286 DisplayChanges changes{};
1287 for (size_t i = 0; i < composition_types.size(); i++) {
1288 changes.AddLayerCompositionChange(display_id, changed_layers[i],
1289 composition_types[i]);
1290 }
1291
1292 std::vector<DisplayRequest::LayerRequest> layer_requests;
1293 for (size_t i = 0; i < requested_layers.size(); i++) {
1294 layer_requests.push_back({requested_layers[i], request_masks[i]});
1295 }
1296
1297 const DisplayRequest request_changes{display_id, display_request_mask,
1298 layer_requests};
1299 changes.display_request_changes = request_changes;
1300
1301 cmd_result_writer_->AddChanges(changes);
1302 composer_resources_->SetDisplayMustValidateState(display_id, false);
1303}
1304
1305void ComposerClient::ExecuteAcceptDisplayChanges(int64_t display_id) {
1306 auto* display = GetDisplay(display_id);
1307 if (display == nullptr) {
1308 cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
1309 return;
1310 }
1311
1312 auto error = Hwc2toHwc3Error(display->AcceptDisplayChanges());
1313 if (error != hwc3::Error::kNone) {
1314 cmd_result_writer_->AddError(error);
1315 return;
1316 }
1317}
1318
1319void ComposerClient::ExecutePresentDisplay(int64_t display_id) {
1320 auto* display = GetDisplay(display_id);
1321 if (display == nullptr) {
1322 cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
1323 return;
1324 }
1325
1326 ::android::base::unique_fd display_fence;
1327 std::unordered_map<int64_t, ::android::base::unique_fd> release_fences;
1328 auto error = PresentDisplayInternal(display_id, display_fence,
1329 release_fences);
1330 if (error != hwc3::Error::kNone) {
1331 cmd_result_writer_->AddError(error);
1332 }
1333 if (cmd_result_writer_->HasError()) {
1334 return;
1335 }
1336
1337 cmd_result_writer_->AddPresentFence(display_id, std::move(display_fence));
1338 cmd_result_writer_->AddReleaseFence(display_id, release_fences);
1339}
1340
1341void ComposerClient::ExecutePresentOrValidateDisplay(
1342 int64_t display_id,
1343 std::optional<ClockMonotonicTimestamp> expected_present_time) {
1344 auto* display = GetDisplay(display_id);
1345 if (display == nullptr) {
1346 cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
1347 return;
1348 }
1349
1350 /* TODO: Handle expectedPresentTime */
Normunds Rieksts42820952024-03-12 15:42:06 +00001351 /* This can be implemented in multiple ways. For example, the expected present
1352 * time property can be implemented by the DRM driver directly as a CRTC
1353 * property. See:
1354 * https://cs.android.com/android/platform/superproject/main/+/b8b3b1646e64d0235f77b9e717a3e4082e26f2a8:hardware/google/graphics/common/libhwc2.1/libdrmresource/drm/drmcrtc.cpp;drc=468f6172546ab98983de18210222f231f16b21e1;l=88
1355 * Unfortunately there doesn't seem to be a standardised way of delaying
1356 * presentation with a timestamp in the DRM API. What we can do alternatively
1357 * is to spawn a separate presentation thread that could handle the VBlank
1358 * events by using DRM_MODE_PAGE_FLIP_EVENT and schedule them appropriately.
1359 */
1360
Drew Davenport5951b112024-08-05 09:44:27 -06001361 /* TODO: Add check if it's possible to skip display validation */
1362 ExecuteValidateDisplay(display_id, expected_present_time);
1363 cmd_result_writer_
1364 ->AddPresentOrValidateResult(display_id,
1365 PresentOrValidate::Result::Validated);
1366}
1367
Dennis Tsiang33f0ece2023-11-29 12:45:04 +00001368} // namespace aidl::android::hardware::graphics::composer3::impl