blob: 60cafad26fb3a3f67fb8cef230eb03c99decb130 [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 Davenport1afb5792024-09-24 12:53:22 -060052using ::android::HwcDisplayConfig;
Drew Davenportf7e88332024-09-06 12:54:38 -060053using ::android::HwcDisplayConfigs;
Drew Davenporta241a772024-09-24 11:26:30 -060054using ::android::HwcLayer;
Dennis Tsiang33f0ece2023-11-29 12:45:04 +000055
56#include "utils/log.h"
57
58namespace aidl::android::hardware::graphics::composer3::impl {
Drew Davenport5951b112024-08-05 09:44:27 -060059namespace {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +000060
Drew Davenport5951b112024-08-05 09:44:27 -060061// clang-format off
62constexpr std::array<float, 16> kIdentityMatrix = {
63 1.0F, 0.0F, 0.0F, 0.0F,
64 0.0F, 1.0F, 0.0F, 0.0F,
65 0.0F, 0.0F, 1.0F, 0.0F,
66 0.0F, 0.0F, 0.0F, 1.0F,
67};
68// clang-format on
Dennis Tsiang33f0ece2023-11-29 12:45:04 +000069
Drew Davenporta241a772024-09-24 11:26:30 -060070std::optional<BufferBlendMode> AidlToBlendMode(
71 const std::optional<ParcelableBlendMode>& aidl_blend_mode) {
72 if (!aidl_blend_mode) {
73 return std::nullopt;
74 }
75
76 switch (aidl_blend_mode->blendMode) {
77 case common::BlendMode::NONE:
78 return BufferBlendMode::kNone;
79 case common::BlendMode::PREMULTIPLIED:
80 return BufferBlendMode::kPreMult;
81 case common::BlendMode::COVERAGE:
82 return BufferBlendMode::kCoverage;
83 case common::BlendMode::INVALID:
84 ALOGE("Invalid BlendMode");
85 return std::nullopt;
86 }
87}
88
Drew Davenportac9681e2024-09-24 12:17:34 -060089std::optional<BufferColorSpace> AidlToColorSpace(
90 const std::optional<ParcelableDataspace>& dataspace) {
91 if (!dataspace) {
92 return std::nullopt;
93 }
94
95 int32_t standard = static_cast<int32_t>(dataspace->dataspace) &
96 static_cast<int32_t>(common::Dataspace::STANDARD_MASK);
97 switch (standard) {
98 case static_cast<int32_t>(common::Dataspace::STANDARD_BT709):
99 return BufferColorSpace::kItuRec709;
100 case static_cast<int32_t>(common::Dataspace::STANDARD_BT601_625):
101 case static_cast<int32_t>(common::Dataspace::STANDARD_BT601_625_UNADJUSTED):
102 case static_cast<int32_t>(common::Dataspace::STANDARD_BT601_525):
103 case static_cast<int32_t>(common::Dataspace::STANDARD_BT601_525_UNADJUSTED):
104 return BufferColorSpace::kItuRec601;
105 case static_cast<int32_t>(common::Dataspace::STANDARD_BT2020):
106 case static_cast<int32_t>(
107 common::Dataspace::STANDARD_BT2020_CONSTANT_LUMINANCE):
108 return BufferColorSpace::kItuRec2020;
109 default:
110 ALOGE("Unsupported standard: %d", standard);
111 return std::nullopt;
112 }
113}
114
115std::optional<BufferSampleRange> AidlToSampleRange(
116 const std::optional<ParcelableDataspace>& dataspace) {
117 if (!dataspace) {
118 return std::nullopt;
119 }
120
121 int32_t sample_range = static_cast<int32_t>(dataspace->dataspace) &
122 static_cast<int32_t>(common::Dataspace::RANGE_MASK);
123 switch (sample_range) {
124 case static_cast<int32_t>(common::Dataspace::RANGE_FULL):
125 return BufferSampleRange::kFullRange;
126 case static_cast<int32_t>(common::Dataspace::RANGE_LIMITED):
127 return BufferSampleRange::kLimitedRange;
128 default:
129 ALOGE("Unsupported sample range: %d", sample_range);
130 return std::nullopt;
131 }
132}
133
Drew Davenport1b0d8b72024-09-24 15:31:38 -0600134bool IsSupportedCompositionType(
135 const std::optional<ParcelableComposition> composition) {
136 if (!composition) {
137 return true;
138 }
139 switch (composition->composition) {
140 case Composition::INVALID:
141 case Composition::CLIENT:
142 case Composition::DEVICE:
143 case Composition::SOLID_COLOR:
144 case Composition::CURSOR:
145 return true;
146
147 // Unsupported composition types. Set an error for the current
148 // DisplayCommand and return.
149 case Composition::DISPLAY_DECORATION:
150 case Composition::SIDEBAND:
151 case Composition::REFRESH_RATE_INDICATOR:
152 return false;
153 }
154}
155
156std::optional<HWC2::Composition> AidlToCompositionType(
157 const std::optional<ParcelableComposition> composition) {
158 if (!composition) {
159 return std::nullopt;
160 }
161
162 switch (composition->composition) {
163 case Composition::INVALID:
164 return HWC2::Composition::Invalid;
165 case Composition::CLIENT:
166 return HWC2::Composition::Client;
167 case Composition::DEVICE:
168 return HWC2::Composition::Device;
169 case Composition::SOLID_COLOR:
170 return HWC2::Composition::SolidColor;
171 case Composition::CURSOR:
172 return HWC2::Composition::Cursor;
173
174 // Unsupported composition types.
175 case Composition::DISPLAY_DECORATION:
176 case Composition::SIDEBAND:
177 case Composition::REFRESH_RATE_INDICATOR:
178 ALOGE("Unsupported composition type: %s",
179 toString(composition->composition).c_str());
180 return std::nullopt;
181 }
182}
183
Drew Davenport1afb5792024-09-24 12:53:22 -0600184DisplayConfiguration HwcDisplayConfigToAidlConfiguration(
185 const HwcDisplayConfigs& configs, const HwcDisplayConfig& config) {
186 DisplayConfiguration aidl_configuration =
187 {.configId = static_cast<int32_t>(config.id),
188 .width = config.mode.GetRawMode().hdisplay,
189 .height = config.mode.GetRawMode().vdisplay,
190 .configGroup = static_cast<int32_t>(config.group_id),
191 .vsyncPeriod = config.mode.GetVSyncPeriodNs()};
192
193 if (configs.mm_width != 0) {
194 // ideally this should be vdisplay/mm_heigth, however mm_height
195 // comes from edid parsing and is highly unreliable. Viewing the
196 // rarity of anisotropic displays, falling back to a single value
197 // for dpi yield more correct output.
198 static const float kMmPerInch = 25.4;
199 float dpi = float(config.mode.GetRawMode().hdisplay) * kMmPerInch /
200 float(configs.mm_width);
201 aidl_configuration.dpi = {.x = dpi, .y = dpi};
202 }
203 // TODO: Populate vrrConfig.
204 return aidl_configuration;
205}
206
Drew Davenport22d66b42024-09-24 15:34:57 -0600207std::optional<hwc_rect> AidlToRect(const std::optional<common::Rect>& rect) {
208 if (!rect) {
209 return std::nullopt;
210 }
211 return hwc_rect{rect->left, rect->top, rect->right, rect->bottom};
212}
213
Drew Davenport5951b112024-08-05 09:44:27 -0600214} // namespace
215
216ComposerClient::ComposerClient() {
217 DEBUG_FUNC();
218}
219
220bool ComposerClient::Init() {
221 DEBUG_FUNC();
222 composer_resources_ = ComposerResources::Create();
223 if (composer_resources_) {
224 hwc_ = std::make_unique<DrmHwcThree>(composer_resources_.get());
225 }
226 return composer_resources_ != nullptr;
227}
228
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000229ComposerClient::~ComposerClient() {
230 DEBUG_FUNC();
Drew Davenport1ac3b622024-09-05 10:59:16 -0600231 {
232 // First Deinit the displays to start shutting down the Display's dependent
233 // threads such as VSyncWorker.
234 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
235 hwc_->DeinitDisplays();
236 }
237 // Sleep to wait for threads to complete and exit.
238 const int time_for_threads_to_exit_us = 200000;
239 usleep(time_for_threads_to_exit_us);
240 {
241 // Hold the lock while destructing the hwc_ and the objects that it owns.
242 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
243 hwc_.reset();
244 }
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000245 LOG(DEBUG) << "removed composer client";
246}
247
Drew Davenport5951b112024-08-05 09:44:27 -0600248ndk::ScopedAStatus ComposerClient::createLayer(int64_t display_id,
249 int32_t buffer_slot_count,
250 int64_t* layer_id) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000251 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600252 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
253
254 HwcDisplay* display = GetDisplay(display_id);
255 if (display == nullptr) {
256 return ToBinderStatus(hwc3::Error::kBadDisplay);
257 }
258
259 hwc2_layer_t hwc2_layer_id = 0;
260 auto err = Hwc2toHwc3Error(display->CreateLayer(&hwc2_layer_id));
261 if (err != hwc3::Error::kNone) {
262 return ToBinderStatus(err);
263 }
264
265 const int64_t created_layer_id = Hwc2LayerToHwc3(hwc2_layer_id);
266 err = composer_resources_->AddLayer(display_id, created_layer_id,
267 buffer_slot_count);
268 if (err != hwc3::Error::kNone) {
269 destroyLayer(display_id, created_layer_id);
270 return ToBinderStatus(err);
271 }
272
273 *layer_id = created_layer_id;
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000274 return ndk::ScopedAStatus::ok();
275}
276
277ndk::ScopedAStatus ComposerClient::createVirtualDisplay(
Drew Davenport5951b112024-08-05 09:44:27 -0600278 int32_t width, int32_t height, AidlPixelFormat format_hint,
279 int32_t output_buffer_slot_count, VirtualDisplay* out_display) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000280 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600281 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
282
283 hwc2_display_t hwc2_display_id = 0;
284 // TODO: Format is currently not used in drm_hwcomposer.
285 int32_t hwc2_format = 0;
286 auto err = Hwc2toHwc3Error(hwc_->CreateVirtualDisplay(width, height,
287 &hwc2_format,
288 &hwc2_display_id));
289 if (err != hwc3::Error::kNone) {
290 return ToBinderStatus(err);
291 }
292
293 const int64_t created_display_id = Hwc2DisplayToHwc3(hwc2_display_id);
294 err = composer_resources_->AddVirtualDisplay(hwc2_display_id,
295 output_buffer_slot_count);
296 if (err != hwc3::Error::kNone) {
297 hwc_->DestroyVirtualDisplay(hwc2_display_id);
298 return ToBinderStatus(err);
299 }
300
301 out_display->display = created_display_id;
302 out_display->format = format_hint;
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000303 return ndk::ScopedAStatus::ok();
304}
305
Drew Davenport5951b112024-08-05 09:44:27 -0600306ndk::ScopedAStatus ComposerClient::destroyLayer(int64_t display_id,
307 int64_t layer_id) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000308 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600309 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
310 HwcDisplay* display = GetDisplay(display_id);
311 if (display == nullptr) {
312 return ToBinderStatus(hwc3::Error::kBadDisplay);
313 }
314
315 auto err = Hwc2toHwc3Error(display->DestroyLayer(Hwc3LayerToHwc2(layer_id)));
316 if (err != hwc3::Error::kNone) {
317 return ToBinderStatus(err);
318 }
319
320 err = composer_resources_->RemoveLayer(display_id, layer_id);
321 return ToBinderStatus(err);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000322}
323
Drew Davenport5951b112024-08-05 09:44:27 -0600324ndk::ScopedAStatus ComposerClient::destroyVirtualDisplay(int64_t display_id) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000325 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600326 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
327 auto err = Hwc2toHwc3Error(hwc_->DestroyVirtualDisplay(display_id));
328 return ToBinderStatus(err);
329}
330
331hwc3::Error ComposerClient::ValidateDisplayInternal(
332 HwcDisplay& display, std::vector<int64_t>* out_changed_layers,
333 std::vector<Composition>* out_composition_types,
334 int32_t* out_display_request_mask,
335 std::vector<int64_t>* out_requested_layers,
336 std::vector<int32_t>* out_request_masks,
337 ClientTargetProperty* /*out_client_target_property*/,
338 DimmingStage* /*out_dimming_stage*/) {
339 DEBUG_FUNC();
340
341 uint32_t num_types = 0;
342 uint32_t num_requests = 0;
343 const HWC2::Error hwc2_error = display.ValidateDisplay(&num_types,
344 &num_requests);
345
346 /* Check if display has pending changes and no errors */
347 if (hwc2_error != HWC2::Error::None &&
348 hwc2_error != HWC2::Error::HasChanges) {
349 return Hwc2toHwc3Error(hwc2_error);
350 }
351
Drew Davenport3f4469f2024-10-03 10:01:51 -0600352 hwc3::Error error = Hwc2toHwc3Error(
353 display.GetChangedCompositionTypes(&num_types, nullptr, nullptr));
354 if (error != hwc3::Error::kNone) {
355 return error;
356 }
357
Drew Davenport5951b112024-08-05 09:44:27 -0600358 std::vector<hwc2_layer_t> hwc_changed_layers(num_types);
359 std::vector<int32_t> hwc_composition_types(num_types);
Drew Davenport3f4469f2024-10-03 10:01:51 -0600360 error = Hwc2toHwc3Error(
Drew Davenport5951b112024-08-05 09:44:27 -0600361 display.GetChangedCompositionTypes(&num_types, hwc_changed_layers.data(),
362 hwc_composition_types.data()));
363 if (error != hwc3::Error::kNone) {
364 return error;
365 }
366
367 int32_t display_reqs = 0;
368 out_request_masks->resize(num_requests);
369 std::vector<hwc2_layer_t> hwc_requested_layers(num_requests);
370 error = Hwc2toHwc3Error(
371 display.GetDisplayRequests(&display_reqs, &num_requests,
372 hwc_requested_layers.data(),
373 out_request_masks->data()));
374 if (error != hwc3::Error::kNone) {
375 return error;
376 }
377
378 for (const auto& layer : hwc_changed_layers) {
379 out_changed_layers->emplace_back(Hwc2LayerToHwc3(layer));
380 }
381 for (const auto& type : hwc_composition_types) {
382 out_composition_types->emplace_back(Hwc2CompositionTypeToHwc3(type));
383 }
384 for (const auto& layer : hwc_requested_layers) {
385 out_requested_layers->emplace_back(Hwc2LayerToHwc3(layer));
386 }
387 *out_display_request_mask = display_reqs;
388
389 /* Client target property/dimming stage unsupported */
390 return hwc3::Error::kNone;
391}
392
393hwc3::Error ComposerClient::PresentDisplayInternal(
394 uint64_t display_id, ::android::base::unique_fd& out_display_fence,
395 std::unordered_map<int64_t, ::android::base::unique_fd>&
396 out_release_fences) {
397 DEBUG_FUNC();
398 auto* display = GetDisplay(display_id);
399 if (display == nullptr) {
400 return hwc3::Error::kBadDisplay;
401 }
402
403 if (composer_resources_->MustValidateDisplay(display_id)) {
404 return hwc3::Error::kNotValidated;
405 }
406
407 int32_t present_fence = -1;
408 auto error = Hwc2toHwc3Error(display->PresentDisplay(&present_fence));
409 if (error != hwc3::Error::kNone) {
410 return error;
411 }
412 out_display_fence.reset(present_fence);
413
414 uint32_t release_fence_count = 0;
415 error = Hwc2toHwc3Error(
416 display->GetReleaseFences(&release_fence_count, nullptr, nullptr));
417 if (error != hwc3::Error::kNone) {
418 return error;
419 }
420
421 std::vector<hwc2_layer_t> hwc_layers(release_fence_count);
422 std::vector<int32_t> hwc_fences(release_fence_count);
423 error = Hwc2toHwc3Error(display->GetReleaseFences(&release_fence_count,
424 hwc_layers.data(),
425 hwc_fences.data()));
426 if (error != hwc3::Error::kNone) {
427 return error;
428 }
429
430 for (size_t i = 0; i < hwc_layers.size(); i++) {
431 auto layer = Hwc2LayerToHwc3(hwc_layers[i]);
432 out_release_fences[layer] = ::android::base::unique_fd{hwc_fences[i]};
433 }
434
435 return hwc3::Error::kNone;
436}
437
438::android::HwcDisplay* ComposerClient::GetDisplay(uint64_t display_id) {
439 return hwc_->GetDisplay(display_id);
440}
441
442void ComposerClient::DispatchLayerCommand(int64_t display_id,
443 const LayerCommand& command) {
444 auto* display = GetDisplay(display_id);
445 if (display == nullptr) {
446 cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
447 return;
448 }
449
450 auto* layer = display->get_layer(command.layer);
451 if (layer == nullptr) {
452 cmd_result_writer_->AddError(hwc3::Error::kBadLayer);
453 return;
454 }
455
Drew Davenport1b0d8b72024-09-24 15:31:38 -0600456 // If the requested composition type is not supported, the HWC should return
457 // an error and not process any further commands.
458 if (!IsSupportedCompositionType(command.composition)) {
459 cmd_result_writer_->AddError(hwc3::Error::kUnsupported);
460 return;
461 }
462
Drew Davenport5951b112024-08-05 09:44:27 -0600463 HwcLayerWrapper layer_wrapper{command.layer, layer};
464 if (command.buffer) {
465 ExecuteSetLayerBuffer(display_id, layer_wrapper, *command.buffer);
466 }
Drew Davenport1b0d8b72024-09-24 15:31:38 -0600467
Drew Davenporta241a772024-09-24 11:26:30 -0600468 HwcLayer::LayerProperties properties;
469 properties.blend_mode = AidlToBlendMode(command.blendMode);
Drew Davenportac9681e2024-09-24 12:17:34 -0600470 properties.color_space = AidlToColorSpace(command.dataspace);
471 properties.sample_range = AidlToSampleRange(command.dataspace);
Drew Davenport1b0d8b72024-09-24 15:31:38 -0600472 properties.composition_type = AidlToCompositionType(command.composition);
Drew Davenport22d66b42024-09-24 15:34:57 -0600473 properties.display_frame = AidlToRect(command.displayFrame);
Drew Davenporta241a772024-09-24 11:26:30 -0600474 layer->SetLayerProperties(properties);
475
Drew Davenport5951b112024-08-05 09:44:27 -0600476 if (command.planeAlpha) {
477 ExecuteSetLayerPlaneAlpha(display_id, layer_wrapper, *command.planeAlpha);
478 }
479 if (command.sourceCrop) {
480 ExecuteSetLayerSourceCrop(display_id, layer_wrapper, *command.sourceCrop);
481 }
482 if (command.transform) {
483 ExecuteSetLayerTransform(display_id, layer_wrapper, *command.transform);
484 }
485 if (command.z) {
486 ExecuteSetLayerZOrder(display_id, layer_wrapper, *command.z);
487 }
488 if (command.brightness) {
489 ExecuteSetLayerBrightness(display_id, layer_wrapper, *command.brightness);
490 }
491
492 // Some unsupported functionality returns kUnsupported, and others
493 // are just a no-op.
494 // TODO: Audit whether some of these should actually return kUnsupported
495 // instead.
496 if (command.sidebandStream) {
497 cmd_result_writer_->AddError(hwc3::Error::kUnsupported);
498 }
499 // TODO: Blocking region handling missing.
500 // TODO: Layer surface damage.
501 // TODO: Layer visible region.
502 // TODO: Per-frame metadata.
503 // TODO: Layer color transform.
504 // TODO: Layer cursor position.
505 // TODO: Layer color.
506}
507
508void ComposerClient::ExecuteDisplayCommand(const DisplayCommand& command) {
509 const int64_t display_id = command.display;
510 if (hwc_->GetDisplay(display_id) == nullptr) {
511 cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
512 return;
513 }
514
515 for (const auto& layer_cmd : command.layers) {
516 DispatchLayerCommand(command.display, layer_cmd);
517 }
518
519 if (command.brightness) {
520 ExecuteSetDisplayBrightness(command.display, *command.brightness);
521 }
522 if (command.colorTransformMatrix) {
523 ExecuteSetDisplayColorTransform(command.display,
524 *command.colorTransformMatrix);
525 }
526 if (command.clientTarget) {
527 ExecuteSetDisplayClientTarget(command.display, *command.clientTarget);
528 }
529 if (command.virtualDisplayOutputBuffer) {
530 ExecuteSetDisplayOutputBuffer(command.display,
531 *command.virtualDisplayOutputBuffer);
532 }
533 if (command.validateDisplay) {
534 ExecuteValidateDisplay(command.display, command.expectedPresentTime);
535 }
536 if (command.acceptDisplayChanges) {
537 ExecuteAcceptDisplayChanges(command.display);
538 }
539 if (command.presentDisplay) {
540 ExecutePresentDisplay(command.display);
541 }
542 if (command.presentOrValidateDisplay) {
543 ExecutePresentOrValidateDisplay(command.display,
544 command.expectedPresentTime);
545 }
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000546}
547
548ndk::ScopedAStatus ComposerClient::executeCommands(
Drew Davenport5951b112024-08-05 09:44:27 -0600549 const std::vector<DisplayCommand>& commands,
550 std::vector<CommandResultPayload>* results) {
Drew Davenport49965852024-09-05 10:59:40 -0600551 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
552 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600553 cmd_result_writer_ = std::make_unique<CommandResultWriter>(results);
554 for (const auto& cmd : commands) {
555 ExecuteDisplayCommand(cmd);
556 cmd_result_writer_->IncrementCommand();
557 }
558 cmd_result_writer_.reset();
559
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000560 return ndk::ScopedAStatus::ok();
561}
562
Drew Davenport5951b112024-08-05 09:44:27 -0600563ndk::ScopedAStatus ComposerClient::getActiveConfig(int64_t display_id,
564 int32_t* config) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000565 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600566 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
567 HwcDisplay* display = GetDisplay(display_id);
568 if (display == nullptr) {
569 return ToBinderStatus(hwc3::Error::kBadDisplay);
570 }
571
572 uint32_t hwc2_config = 0;
573 const hwc3::Error error = Hwc2toHwc3Error(
574 display->GetActiveConfig(&hwc2_config));
575 if (error != hwc3::Error::kNone) {
576 return ToBinderStatus(error);
577 }
578 *config = Hwc2ConfigIdToHwc3(hwc2_config);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000579 return ndk::ScopedAStatus::ok();
580}
581
582ndk::ScopedAStatus ComposerClient::getColorModes(
Drew Davenport5951b112024-08-05 09:44:27 -0600583 int64_t display_id, std::vector<ColorMode>* color_modes) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000584 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600585 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
586 HwcDisplay* display = GetDisplay(display_id);
587 if (display == nullptr) {
588 return ToBinderStatus(hwc3::Error::kBadDisplay);
589 }
590
591 uint32_t num_modes = 0;
592 auto error = Hwc2toHwc3Error(display->GetColorModes(&num_modes, nullptr));
593 if (error != hwc3::Error::kNone) {
594 return ToBinderStatus(error);
595 }
596
597 std::vector<int32_t> hwc2_color_modes(num_modes);
598 error = Hwc2toHwc3Error(
599 display->GetColorModes(&num_modes, hwc2_color_modes.data()));
600 if (error != hwc3::Error::kNone) {
601 return ToBinderStatus(error);
602 }
603
604 for (const auto& mode : hwc2_color_modes) {
605 color_modes->push_back(Hwc2ColorModeToHwc3(mode));
606 }
607
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000608 return ndk::ScopedAStatus::ok();
609}
610
611ndk::ScopedAStatus ComposerClient::getDataspaceSaturationMatrix(
Drew Davenport5951b112024-08-05 09:44:27 -0600612 common::Dataspace dataspace, std::vector<float>* matrix) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000613 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600614 if (dataspace != common::Dataspace::SRGB_LINEAR) {
615 return ToBinderStatus(hwc3::Error::kBadParameter);
616 }
617
618 matrix->clear();
619 matrix->insert(matrix->begin(), kIdentityMatrix.begin(),
620 kIdentityMatrix.end());
621
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000622 return ndk::ScopedAStatus::ok();
623}
624
625ndk::ScopedAStatus ComposerClient::getDisplayAttribute(
Drew Davenport1afb5792024-09-24 12:53:22 -0600626 int64_t display_id, int32_t config_id, DisplayAttribute attribute,
Drew Davenport5951b112024-08-05 09:44:27 -0600627 int32_t* value) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000628 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600629 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
630 HwcDisplay* display = GetDisplay(display_id);
631 if (display == nullptr) {
632 return ToBinderStatus(hwc3::Error::kBadDisplay);
633 }
634
Drew Davenport1afb5792024-09-24 12:53:22 -0600635 const HwcDisplayConfigs& configs = display->GetDisplayConfigs();
636 auto config = configs.hwc_configs.find(config_id);
637 if (config == configs.hwc_configs.end()) {
638 return ToBinderStatus(hwc3::Error::kBadConfig);
639 }
640
641 DisplayConfiguration
642 aidl_configuration = HwcDisplayConfigToAidlConfiguration(configs,
643 config->second);
644 // Legacy API for querying DPI uses units of dots per 1000 inches.
645 static const int kLegacyDpiUnit = 1000;
646 switch (attribute) {
647 case DisplayAttribute::WIDTH:
648 *value = aidl_configuration.width;
649 break;
650 case DisplayAttribute::HEIGHT:
651 *value = aidl_configuration.height;
652 break;
653 case DisplayAttribute::VSYNC_PERIOD:
654 *value = aidl_configuration.vsyncPeriod;
655 break;
656 case DisplayAttribute::DPI_X:
657 *value = aidl_configuration.dpi
658 ? static_cast<int>(aidl_configuration.dpi->x *
659 kLegacyDpiUnit)
660 : -1;
661 break;
662 case DisplayAttribute::DPI_Y:
663 *value = aidl_configuration.dpi
664 ? static_cast<int>(aidl_configuration.dpi->y *
665 kLegacyDpiUnit)
666 : -1;
667 break;
668 case DisplayAttribute::CONFIG_GROUP:
669 *value = aidl_configuration.configGroup;
670 break;
671 case DisplayAttribute::INVALID:
672 return ToBinderStatus(hwc3::Error::kUnsupported);
673 }
674 return ndk::ScopedAStatus::ok();
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000675}
676
677ndk::ScopedAStatus ComposerClient::getDisplayCapabilities(
Drew Davenport5951b112024-08-05 09:44:27 -0600678 int64_t display_id, std::vector<DisplayCapability>* caps) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000679 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600680 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
681 HwcDisplay* display = GetDisplay(display_id);
682 if (display == nullptr) {
683 return ToBinderStatus(hwc3::Error::kBadDisplay);
684 }
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000685
Drew Davenport5951b112024-08-05 09:44:27 -0600686 uint32_t num_capabilities = 0;
687 hwc3::Error error = Hwc2toHwc3Error(
688 display->GetDisplayCapabilities(&num_capabilities, nullptr));
689 if (error != hwc3::Error::kNone) {
690 return ToBinderStatus(error);
691 }
692
693 std::vector<uint32_t> out_caps(num_capabilities);
694 error = Hwc2toHwc3Error(
695 display->GetDisplayCapabilities(&num_capabilities, out_caps.data()));
696 if (error != hwc3::Error::kNone) {
697 return ToBinderStatus(error);
698 }
699
700 caps->reserve(num_capabilities);
701 for (const auto cap : out_caps) {
702 caps->emplace_back(Hwc2DisplayCapabilityToHwc3(cap));
703 }
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000704 return ndk::ScopedAStatus::ok();
705}
706
707ndk::ScopedAStatus ComposerClient::getDisplayConfigs(
Drew Davenport1afb5792024-09-24 12:53:22 -0600708 int64_t display_id, std::vector<int32_t>* out_configs) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000709 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600710 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
711 HwcDisplay* display = GetDisplay(display_id);
712 if (display == nullptr) {
713 return ToBinderStatus(hwc3::Error::kBadDisplay);
714 }
715
Drew Davenport1afb5792024-09-24 12:53:22 -0600716 const HwcDisplayConfigs& configs = display->GetDisplayConfigs();
717 for (const auto& [id, config] : configs.hwc_configs) {
718 out_configs->push_back(static_cast<int32_t>(id));
Drew Davenport5951b112024-08-05 09:44:27 -0600719 }
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000720 return ndk::ScopedAStatus::ok();
721}
722
723ndk::ScopedAStatus ComposerClient::getDisplayConnectionType(
Drew Davenport5951b112024-08-05 09:44:27 -0600724 int64_t display_id, DisplayConnectionType* type) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000725 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600726 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
727 HwcDisplay* display = GetDisplay(display_id);
728 if (display == nullptr) {
729 return ToBinderStatus(hwc3::Error::kBadDisplay);
730 }
731
732 uint32_t out_type = 0;
733 const hwc3::Error error = Hwc2toHwc3Error(
734 display->GetDisplayConnectionType(&out_type));
735 if (error != hwc3::Error::kNone) {
736 return ToBinderStatus(error);
737 }
738
739 *type = Hwc2DisplayConnectionTypeToHwc3(out_type);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000740 return ndk::ScopedAStatus::ok();
741}
742
743ndk::ScopedAStatus ComposerClient::getDisplayIdentificationData(
Drew Davenport5951b112024-08-05 09:44:27 -0600744 int64_t display_id, DisplayIdentification* id) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000745 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600746 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
747 HwcDisplay* display = GetDisplay(display_id);
748 if (display == nullptr) {
749 return ToBinderStatus(hwc3::Error::kBadDisplay);
750 }
751
752 uint8_t port = 0;
753 uint32_t data_size = 0;
754 hwc3::Error error = Hwc2toHwc3Error(
755 display->GetDisplayIdentificationData(&port, &data_size, nullptr));
756 if (error != hwc3::Error::kNone) {
757 return ToBinderStatus(error);
758 }
759
760 id->data.resize(data_size);
761 error = Hwc2toHwc3Error(
762 display->GetDisplayIdentificationData(&port, &data_size,
763 id->data.data()));
764 if (error != hwc3::Error::kNone) {
765 return ToBinderStatus(error);
766 }
767
768 id->port = static_cast<int8_t>(port);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000769 return ndk::ScopedAStatus::ok();
770}
771
Drew Davenport5951b112024-08-05 09:44:27 -0600772ndk::ScopedAStatus ComposerClient::getDisplayName(int64_t display_id,
773 std::string* name) {
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 uint32_t size = 0;
782 auto error = Hwc2toHwc3Error(display->GetDisplayName(&size, nullptr));
783 if (error != hwc3::Error::kNone) {
784 return ToBinderStatus(error);
785 }
786
787 name->resize(size);
788 error = Hwc2toHwc3Error(display->GetDisplayName(&size, name->data()));
789 return ToBinderStatus(error);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000790}
791
792ndk::ScopedAStatus ComposerClient::getDisplayVsyncPeriod(
Drew Davenport5951b112024-08-05 09:44:27 -0600793 int64_t display_id, int32_t* vsync_period) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000794 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600795 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
796 HwcDisplay* display = GetDisplay(display_id);
797 if (display == nullptr) {
798 return ToBinderStatus(hwc3::Error::kBadDisplay);
799 }
800
801 uint32_t hwc2_vsync_period = 0;
802 auto error = Hwc2toHwc3Error(
803 display->GetDisplayVsyncPeriod(&hwc2_vsync_period));
804 if (error != hwc3::Error::kNone) {
805 return ToBinderStatus(error);
806 }
807
808 *vsync_period = static_cast<int32_t>(hwc2_vsync_period);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000809 return ndk::ScopedAStatus::ok();
810}
811
812ndk::ScopedAStatus ComposerClient::getDisplayedContentSample(
Drew Davenport5951b112024-08-05 09:44:27 -0600813 int64_t /*display_id*/, int64_t /*max_frames*/, int64_t /*timestamp*/,
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000814 DisplayContentSample* /*samples*/) {
815 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600816 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000817}
818
819ndk::ScopedAStatus ComposerClient::getDisplayedContentSamplingAttributes(
Drew Davenport5951b112024-08-05 09:44:27 -0600820 int64_t /*display_id*/, DisplayContentSamplingAttributes* /*attrs*/) {
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::getDisplayPhysicalOrientation(
Drew Davenport5951b112024-08-05 09:44:27 -0600826 int64_t display_id, common::Transform* orientation) {
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 HwcDisplay* display = GetDisplay(display_id);
830 if (display == nullptr) {
831 return ToBinderStatus(hwc3::Error::kBadDisplay);
832 }
833
834 *orientation = common::Transform::NONE;
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000835 return ndk::ScopedAStatus::ok();
836}
837
Drew Davenport5951b112024-08-05 09:44:27 -0600838ndk::ScopedAStatus ComposerClient::getHdrCapabilities(int64_t display_id,
839 HdrCapabilities* caps) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000840 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600841 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
842 HwcDisplay* display = GetDisplay(display_id);
843 if (display == nullptr) {
844 return ToBinderStatus(hwc3::Error::kBadDisplay);
845 }
846
847 /* No HDR capabilities */
848 caps->types.clear();
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000849 return ndk::ScopedAStatus::ok();
850}
851
Drew Davenport5951b112024-08-05 09:44:27 -0600852ndk::ScopedAStatus ComposerClient::getMaxVirtualDisplayCount(int32_t* count) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000853 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600854 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
855 *count = static_cast<int32_t>(hwc_->GetMaxVirtualDisplayCount());
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000856 return ndk::ScopedAStatus::ok();
857}
858
859ndk::ScopedAStatus ComposerClient::getPerFrameMetadataKeys(
Drew Davenport5951b112024-08-05 09:44:27 -0600860 int64_t /*display_id*/, std::vector<PerFrameMetadataKey>* /*keys*/) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000861 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600862 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000863}
864
865ndk::ScopedAStatus ComposerClient::getReadbackBufferAttributes(
Drew Davenport5951b112024-08-05 09:44:27 -0600866 int64_t /*display_id*/, ReadbackBufferAttributes* /*attrs*/) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000867 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600868 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000869}
870
871ndk::ScopedAStatus ComposerClient::getReadbackBufferFence(
Drew Davenport5951b112024-08-05 09:44:27 -0600872 int64_t /*display_id*/, ndk::ScopedFileDescriptor* /*acquireFence*/) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000873 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600874 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000875}
876
877ndk::ScopedAStatus ComposerClient::getRenderIntents(
Drew Davenport5951b112024-08-05 09:44:27 -0600878 int64_t display_id, ColorMode mode, std::vector<RenderIntent>* intents) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000879 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600880 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
881 HwcDisplay* display = GetDisplay(display_id);
882 if (display == nullptr) {
883 return ToBinderStatus(hwc3::Error::kBadDisplay);
884 }
885
886 const int32_t hwc2_color_mode = Hwc3ColorModeToHwc2(mode);
887 uint32_t out_num_intents = 0;
888 auto error = Hwc2toHwc3Error(
889 display->GetRenderIntents(hwc2_color_mode, &out_num_intents, nullptr));
890 if (error != hwc3::Error::kNone) {
891 return ToBinderStatus(error);
892 }
893
894 std::vector<int32_t> out_intents(out_num_intents);
895 error = Hwc2toHwc3Error(display->GetRenderIntents(hwc2_color_mode,
896 &out_num_intents,
897 out_intents.data()));
898 if (error != hwc3::Error::kNone) {
899 return ToBinderStatus(error);
900 }
901
902 intents->reserve(out_num_intents);
903 for (const auto intent : out_intents) {
904 intents->emplace_back(Hwc2RenderIntentToHwc3(intent));
905 }
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000906 return ndk::ScopedAStatus::ok();
907}
908
909ndk::ScopedAStatus ComposerClient::getSupportedContentTypes(
Drew Davenport5951b112024-08-05 09:44:27 -0600910 int64_t display_id, std::vector<ContentType>* types) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000911 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600912 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
913 HwcDisplay* display = GetDisplay(display_id);
914 if (display == nullptr) {
915 return ToBinderStatus(hwc3::Error::kBadDisplay);
916 }
917
Drew Davenport8d38dc72024-09-24 12:26:07 -0600918 // Support for ContentType is not implemented.
919 types->clear();
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000920 return ndk::ScopedAStatus::ok();
921}
922
923ndk::ScopedAStatus ComposerClient::getDisplayDecorationSupport(
Drew Davenport5951b112024-08-05 09:44:27 -0600924 int64_t /*display_id*/,
925 std::optional<common::DisplayDecorationSupport>* /*support_struct*/) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000926 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600927 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000928}
929
930ndk::ScopedAStatus ComposerClient::registerCallback(
Drew Davenport5951b112024-08-05 09:44:27 -0600931 const std::shared_ptr<IComposerCallback>& callback) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000932 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600933 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
934 // This function is specified to be called exactly once.
935 hwc_->Init(callback);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000936 return ndk::ScopedAStatus::ok();
937}
938
Drew Davenport5951b112024-08-05 09:44:27 -0600939ndk::ScopedAStatus ComposerClient::setActiveConfig(int64_t display_id,
940 int32_t config) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000941 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600942 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
943 HwcDisplay* display = GetDisplay(display_id);
944 if (display == nullptr) {
945 return ToBinderStatus(hwc3::Error::kBadDisplay);
946 }
947
948 return ToBinderStatus(Hwc2toHwc3Error(display->SetActiveConfig(config)));
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000949}
950
951ndk::ScopedAStatus ComposerClient::setActiveConfigWithConstraints(
Drew Davenport5951b112024-08-05 09:44:27 -0600952 int64_t display_id, int32_t config,
953 const VsyncPeriodChangeConstraints& constraints,
954 VsyncPeriodChangeTimeline* timeline) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000955 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600956 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
957 HwcDisplay* display = GetDisplay(display_id);
958 if (display == nullptr) {
959 return ToBinderStatus(hwc3::Error::kBadDisplay);
960 }
961
962 hwc_vsync_period_change_constraints_t hwc2_constraints;
963 hwc2_constraints.desiredTimeNanos = constraints.desiredTimeNanos;
964 hwc2_constraints.seamlessRequired = static_cast<uint8_t>(
965 constraints.seamlessRequired);
966
967 hwc_vsync_period_change_timeline_t hwc2_timeline{};
968 auto error = Hwc2toHwc3Error(
969 display->SetActiveConfigWithConstraints(config, &hwc2_constraints,
970 &hwc2_timeline));
971 if (error != hwc3::Error::kNone) {
972 return ToBinderStatus(error);
973 }
974
975 timeline->refreshTimeNanos = hwc2_timeline.refreshTimeNanos;
976 timeline->newVsyncAppliedTimeNanos = hwc2_timeline.newVsyncAppliedTimeNanos;
977 timeline->refreshRequired = static_cast<bool>(hwc2_timeline.refreshRequired);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000978 return ndk::ScopedAStatus::ok();
979}
980
Drew Davenport5951b112024-08-05 09:44:27 -0600981ndk::ScopedAStatus ComposerClient::setBootDisplayConfig(int64_t /*display_id*/,
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000982 int32_t /*config*/) {
983 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600984 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000985}
986
Drew Davenport5951b112024-08-05 09:44:27 -0600987ndk::ScopedAStatus ComposerClient::clearBootDisplayConfig(
988 int64_t /*display_id*/) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000989 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600990 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000991}
992
993ndk::ScopedAStatus ComposerClient::getPreferredBootDisplayConfig(
Drew Davenport5951b112024-08-05 09:44:27 -0600994 int64_t /*display_id*/, int32_t* /*config*/) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000995 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -0600996 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +0000997}
998
Drew Davenport5951b112024-08-05 09:44:27 -0600999ndk::ScopedAStatus ComposerClient::setAutoLowLatencyMode(int64_t display_id,
1000 bool on) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +00001001 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -06001002 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
1003 HwcDisplay* display = GetDisplay(display_id);
1004 if (display == nullptr) {
1005 return ToBinderStatus(hwc3::Error::kBadDisplay);
1006 }
1007
1008 auto error = Hwc2toHwc3Error(display->SetAutoLowLatencyMode(on));
1009 return ToBinderStatus(error);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +00001010}
1011
Drew Davenport5951b112024-08-05 09:44:27 -06001012ndk::ScopedAStatus ComposerClient::setClientTargetSlotCount(int64_t display_id,
1013 int32_t count) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +00001014 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -06001015 return ToBinderStatus(
1016 composer_resources_->SetDisplayClientTargetCacheSize(display_id, count));
Dennis Tsiang33f0ece2023-11-29 12:45:04 +00001017}
1018
Drew Davenport5951b112024-08-05 09:44:27 -06001019ndk::ScopedAStatus ComposerClient::setColorMode(int64_t display_id,
1020 ColorMode mode,
1021 RenderIntent intent) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +00001022 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -06001023 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
1024 HwcDisplay* display = GetDisplay(display_id);
1025 if (display == nullptr) {
1026 return ToBinderStatus(hwc3::Error::kBadDisplay);
1027 }
1028
1029 auto error = display->SetColorModeWithIntent(Hwc3ColorModeToHwc2(mode),
1030 Hwc3RenderIntentToHwc2(intent));
1031 return ToBinderStatus(Hwc2toHwc3Error(error));
Dennis Tsiang33f0ece2023-11-29 12:45:04 +00001032}
1033
Drew Davenport5951b112024-08-05 09:44:27 -06001034ndk::ScopedAStatus ComposerClient::setContentType(int64_t display_id,
1035 ContentType type) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +00001036 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -06001037 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
1038 HwcDisplay* display = GetDisplay(display_id);
1039 if (display == nullptr) {
1040 return ToBinderStatus(hwc3::Error::kBadDisplay);
1041 }
1042
Drew Davenport8d38dc72024-09-24 12:26:07 -06001043 if (type == ContentType::NONE) {
1044 return ndk::ScopedAStatus::ok();
1045 }
1046 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +00001047}
1048
1049ndk::ScopedAStatus ComposerClient::setDisplayedContentSamplingEnabled(
Drew Davenport5951b112024-08-05 09:44:27 -06001050 int64_t /*display_id*/, bool /*enable*/,
Dennis Tsiang33f0ece2023-11-29 12:45:04 +00001051 FormatColorComponent /*componentMask*/, int64_t /*maxFrames*/) {
1052 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -06001053 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +00001054}
1055
Drew Davenport5951b112024-08-05 09:44:27 -06001056ndk::ScopedAStatus ComposerClient::setPowerMode(int64_t display_id,
1057 PowerMode mode) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +00001058 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -06001059 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
1060 HwcDisplay* display = GetDisplay(display_id);
1061 if (display == nullptr) {
1062 return ToBinderStatus(hwc3::Error::kBadDisplay);
1063 }
1064
Dennis Tsiang1a966202024-01-24 12:46:33 +00001065 if (mode == PowerMode::ON_SUSPEND) {
1066 return ToBinderStatus(hwc3::Error::kUnsupported);
1067 }
1068
Drew Davenport5951b112024-08-05 09:44:27 -06001069 auto error = display->SetPowerMode(Hwc3PowerModeToHwc2(mode));
1070 return ToBinderStatus(Hwc2toHwc3Error(error));
Dennis Tsiang33f0ece2023-11-29 12:45:04 +00001071}
1072
1073ndk::ScopedAStatus ComposerClient::setReadbackBuffer(
Drew Davenport5951b112024-08-05 09:44:27 -06001074 int64_t /*display_id*/, const AidlNativeHandle& /*aidlBuffer*/,
Dennis Tsiang33f0ece2023-11-29 12:45:04 +00001075 const ndk::ScopedFileDescriptor& /*releaseFence*/) {
1076 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -06001077 return ToBinderStatus(hwc3::Error::kUnsupported);
Dennis Tsiang33f0ece2023-11-29 12:45:04 +00001078}
1079
Drew Davenport5951b112024-08-05 09:44:27 -06001080ndk::ScopedAStatus ComposerClient::setVsyncEnabled(int64_t display_id,
1081 bool enabled) {
Dennis Tsiang33f0ece2023-11-29 12:45:04 +00001082 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -06001083 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
1084 HwcDisplay* display = GetDisplay(display_id);
1085 if (display == nullptr) {
1086 return ToBinderStatus(hwc3::Error::kBadDisplay);
1087 }
1088
1089 auto error = display->SetVsyncEnabled(static_cast<int32_t>(enabled));
1090 return ToBinderStatus(Hwc2toHwc3Error(error));
Dennis Tsiang33f0ece2023-11-29 12:45:04 +00001091}
1092
Drew Davenport5951b112024-08-05 09:44:27 -06001093ndk::ScopedAStatus ComposerClient::setIdleTimerEnabled(int64_t /*display_id*/,
Dennis Tsiang33f0ece2023-11-29 12:45:04 +00001094 int32_t /*timeout*/) {
1095 DEBUG_FUNC();
Drew Davenport5951b112024-08-05 09:44:27 -06001096 return ToBinderStatus(hwc3::Error::kUnsupported);
1097}
1098
Drew Davenport7f1761b2024-08-20 10:09:43 -06001099ndk::ScopedAStatus ComposerClient::getOverlaySupport(
1100 OverlayProperties* /*out_overlay_properties*/) {
1101 return ToBinderStatus(hwc3::Error::kUnsupported);
1102}
1103
1104ndk::ScopedAStatus ComposerClient::getHdrConversionCapabilities(
1105 std::vector<common::HdrConversionCapability>* /*out_capabilities*/) {
1106 return ToBinderStatus(hwc3::Error::kUnsupported);
1107}
1108
1109ndk::ScopedAStatus ComposerClient::setHdrConversionStrategy(
1110 const common::HdrConversionStrategy& /*conversion_strategy*/,
1111 common::Hdr* /*out_hdr*/) {
1112 return ToBinderStatus(hwc3::Error::kUnsupported);
1113}
1114
1115ndk::ScopedAStatus ComposerClient::setRefreshRateChangedCallbackDebugEnabled(
1116 int64_t /*display*/, bool /*enabled*/) {
1117 return ToBinderStatus(hwc3::Error::kUnsupported);
1118}
1119
1120ndk::ScopedAStatus ComposerClient::getDisplayConfigurations(
Drew Davenportf7e88332024-09-06 12:54:38 -06001121 int64_t display_id, int32_t /*max_frame_interval_ns*/,
Drew Davenport7f1761b2024-08-20 10:09:43 -06001122 std::vector<DisplayConfiguration>* configurations) {
Drew Davenportf7e88332024-09-06 12:54:38 -06001123 DEBUG_FUNC();
1124 const std::unique_lock lock(hwc_->GetResMan().GetMainLock());
1125 HwcDisplay* display = GetDisplay(display_id);
1126 if (display == nullptr) {
1127 return ToBinderStatus(hwc3::Error::kBadDisplay);
1128 }
1129
1130 const HwcDisplayConfigs& configs = display->GetDisplayConfigs();
1131 for (const auto& [id, config] : configs.hwc_configs) {
Drew Davenport1afb5792024-09-24 12:53:22 -06001132 configurations->push_back(
1133 HwcDisplayConfigToAidlConfiguration(configs, config));
Drew Davenportf7e88332024-09-06 12:54:38 -06001134 }
1135 return ndk::ScopedAStatus::ok();
Drew Davenport7f1761b2024-08-20 10:09:43 -06001136}
1137
1138ndk::ScopedAStatus ComposerClient::notifyExpectedPresent(
1139 int64_t /*display*/, const ClockMonotonicTimestamp& /*expected_present_time*/,
1140 int32_t /*frame_interval_ns*/) {
1141 return ToBinderStatus(hwc3::Error::kUnsupported);
1142}
1143
Drew Davenport5951b112024-08-05 09:44:27 -06001144std::string ComposerClient::Dump() {
1145 uint32_t size = 0;
1146 hwc_->Dump(&size, nullptr);
1147
1148 std::string buffer(size, '\0');
1149 hwc_->Dump(&size, &buffer.front());
1150 return buffer;
Dennis Tsiang33f0ece2023-11-29 12:45:04 +00001151}
1152
1153::ndk::SpAIBinder ComposerClient::createBinder() {
1154 auto binder = BnComposerClient::createBinder();
1155 AIBinder_setInheritRt(binder.get(), true);
1156 return binder;
1157}
1158
Drew Davenport5951b112024-08-05 09:44:27 -06001159void ComposerClient::ExecuteSetLayerBuffer(int64_t display_id,
1160 HwcLayerWrapper& layer,
1161 const Buffer& buffer) {
1162 buffer_handle_t imported_buffer = nullptr;
1163
1164 auto releaser = composer_resources_->CreateResourceReleaser(true);
1165 auto err = composer_resources_->GetLayerBuffer(display_id, layer.layer_id,
1166 buffer, &imported_buffer,
1167 releaser.get());
1168 if (err != hwc3::Error::kNone) {
1169 cmd_result_writer_->AddError(err);
1170 return;
1171 }
1172
1173 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
1174 auto fence_fd = const_cast<ndk::ScopedFileDescriptor&>(buffer.fence)
1175 .release();
1176 err = Hwc2toHwc3Error(layer.layer->SetLayerBuffer(imported_buffer, fence_fd));
1177 if (err != hwc3::Error::kNone) {
1178 cmd_result_writer_->AddError(err);
1179 }
1180}
1181
Drew Davenport5951b112024-08-05 09:44:27 -06001182void ComposerClient::ExecuteSetLayerPlaneAlpha(int64_t /*display_id*/,
1183 HwcLayerWrapper& layer,
1184 const PlaneAlpha& plane_alpha) {
1185 auto err = Hwc2toHwc3Error(
1186 layer.layer->SetLayerPlaneAlpha(plane_alpha.alpha));
1187 if (err != hwc3::Error::kNone) {
1188 cmd_result_writer_->AddError(err);
1189 }
1190}
1191
1192void ComposerClient::ExecuteSetLayerSourceCrop(
1193 int64_t /*display_id*/, HwcLayerWrapper& layer,
1194 const common::FRect& source_crop) {
1195 const hwc_frect_t rect{source_crop.left, source_crop.top, source_crop.right,
1196 source_crop.bottom};
1197 auto err = Hwc2toHwc3Error(layer.layer->SetLayerSourceCrop(rect));
1198 if (err != hwc3::Error::kNone) {
1199 cmd_result_writer_->AddError(err);
1200 }
1201}
1202void ComposerClient::ExecuteSetLayerTransform(
1203 int64_t /*display_id*/, HwcLayerWrapper& layer,
1204 const ParcelableTransform& transform) {
1205 auto err = Hwc2toHwc3Error(
1206 layer.layer->SetLayerTransform(Hwc3TransformToHwc2(transform.transform)));
1207 if (err != hwc3::Error::kNone) {
1208 cmd_result_writer_->AddError(err);
1209 }
1210}
1211void ComposerClient::ExecuteSetLayerZOrder(int64_t /*display_id*/,
1212 HwcLayerWrapper& layer,
1213 const ZOrder& z_order) {
1214 auto err = Hwc2toHwc3Error(layer.layer->SetLayerZOrder(z_order.z));
1215 if (err != hwc3::Error::kNone) {
1216 cmd_result_writer_->AddError(err);
1217 }
1218}
1219
1220void ComposerClient::ExecuteSetLayerBrightness(
1221 int64_t /*display_id*/, HwcLayerWrapper& /*layer*/,
1222 const LayerBrightness& brightness) {
1223 if (std::signbit(brightness.brightness) ||
1224 std::isnan(brightness.brightness)) {
1225 cmd_result_writer_->AddError(hwc3::Error::kBadParameter);
1226 }
1227}
1228
1229void ComposerClient::ExecuteSetDisplayBrightness(
1230 uint64_t display_id, const DisplayBrightness& command) {
1231 auto* display = GetDisplay(display_id);
1232 if (display == nullptr) {
1233 cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
1234 return;
1235 }
1236
1237 auto error = Hwc2toHwc3Error(
1238 display->SetDisplayBrightness(command.brightness));
1239 if (error != hwc3::Error::kNone) {
1240 cmd_result_writer_->AddError(error);
1241 }
1242}
1243void ComposerClient::ExecuteSetDisplayColorTransform(
1244 uint64_t display_id, const std::vector<float>& matrix) {
1245 auto* display = GetDisplay(display_id);
1246 if (display == nullptr) {
1247 cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
1248 return;
1249 }
1250
1251 auto almost_equal = [](auto a, auto b) {
1252 const float epsilon = 0.001F;
1253 return std::abs(a - b) < epsilon;
1254 };
1255 const bool is_identity = std::equal(matrix.begin(), matrix.end(),
1256 kIdentityMatrix.begin(), almost_equal);
1257
1258 const int32_t hint = is_identity ? HAL_COLOR_TRANSFORM_IDENTITY
1259 : HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX;
1260
1261 auto error = Hwc2toHwc3Error(display->SetColorTransform(matrix.data(), hint));
1262 if (error != hwc3::Error::kNone) {
1263 cmd_result_writer_->AddError(error);
1264 }
1265}
1266void ComposerClient::ExecuteSetDisplayClientTarget(
1267 uint64_t display_id, const ClientTarget& command) {
1268 auto* display = GetDisplay(display_id);
1269 if (display == nullptr) {
1270 cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
1271 return;
1272 }
1273
1274 hwc_region_t damage_regions;
1275 damage_regions.numRects = command.damage.size();
1276
1277 std::vector<hwc_rect_t> regions(command.damage.size());
1278 for (const auto& region : command.damage) {
1279 regions.push_back({region.left, region.top, region.right, region.bottom});
1280 }
1281 damage_regions.rects = regions.data();
1282
1283 buffer_handle_t imported_buffer = nullptr;
1284 auto buf_releaser = composer_resources_->CreateResourceReleaser(true);
1285
1286 auto error = composer_resources_->GetDisplayClientTarget(display_id,
1287 command.buffer,
1288 &imported_buffer,
1289 buf_releaser.get());
1290 if (error != hwc3::Error::kNone) {
1291 cmd_result_writer_->AddError(error);
1292 return;
1293 }
1294
1295 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
1296 auto fence = const_cast<::ndk::ScopedFileDescriptor&>(command.buffer.fence)
1297 .release();
1298 error = Hwc2toHwc3Error(
1299 display->SetClientTarget(imported_buffer, fence,
1300 Hwc3DataspaceToHwc2(command.dataspace),
1301 damage_regions));
1302 if (error != hwc3::Error::kNone) {
1303 cmd_result_writer_->AddError(error);
1304 }
1305}
1306
1307void ComposerClient::ExecuteSetDisplayOutputBuffer(uint64_t display_id,
1308 const Buffer& buffer) {
1309 auto* display = GetDisplay(display_id);
1310 if (display == nullptr) {
1311 cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
1312 return;
1313 }
1314
1315 buffer_handle_t imported_buffer = nullptr;
1316 auto buf_releaser = composer_resources_->CreateResourceReleaser(true);
1317
1318 auto error = composer_resources_->GetDisplayOutputBuffer(display_id, buffer,
1319 &imported_buffer,
1320 buf_releaser.get());
1321 if (error != hwc3::Error::kNone) {
1322 cmd_result_writer_->AddError(error);
1323 return;
1324 }
1325
1326 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
1327 auto fence = const_cast<::ndk::ScopedFileDescriptor&>(buffer.fence).release();
1328 error = Hwc2toHwc3Error(display->SetOutputBuffer(imported_buffer, fence));
1329 if (error != hwc3::Error::kNone) {
1330 cmd_result_writer_->AddError(error);
1331 return;
1332 }
1333}
1334void ComposerClient::ExecuteValidateDisplay(
1335 int64_t display_id,
1336 std::optional<ClockMonotonicTimestamp> /*expected_present_time*/
1337) {
1338 auto* display = GetDisplay(display_id);
1339 if (display == nullptr) {
1340 cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
1341 return;
1342 }
1343
1344 /* TODO: Handle expectedPresentTime */
Normunds Rieksts42820952024-03-12 15:42:06 +00001345 /* This can be implemented in multiple ways. For example, the expected present
1346 * time property can be implemented by the DRM driver directly as a CRTC
1347 * property. See:
1348 * https://cs.android.com/android/platform/superproject/main/+/b8b3b1646e64d0235f77b9e717a3e4082e26f2a8:hardware/google/graphics/common/libhwc2.1/libdrmresource/drm/drmcrtc.cpp;drc=468f6172546ab98983de18210222f231f16b21e1;l=88
1349 * Unfortunately there doesn't seem to be a standardised way of delaying
1350 * presentation with a timestamp in the DRM API. What we can do alternatively
1351 * is to spawn a separate presentation thread that could handle the VBlank
1352 * events by using DRM_MODE_PAGE_FLIP_EVENT and schedule them appropriately.
1353 */
Drew Davenport5951b112024-08-05 09:44:27 -06001354
1355 std::vector<int64_t> changed_layers;
1356 std::vector<Composition> composition_types;
1357 int32_t display_request_mask = 0;
1358 std::vector<int64_t> requested_layers;
1359 std::vector<int32_t> request_masks;
1360
1361 const hwc3::Error error = ValidateDisplayInternal(*display, &changed_layers,
1362 &composition_types,
1363 &display_request_mask,
1364 &requested_layers,
1365 &request_masks, nullptr,
1366 nullptr);
1367
1368 if (error != hwc3::Error::kNone) {
1369 cmd_result_writer_->AddError(error);
1370 }
1371
1372 // If a CommandError has been been set for the current DisplayCommand, then
1373 // no other results should be returned besides the error.
1374 if (cmd_result_writer_->HasError()) {
1375 return;
1376 }
1377
1378 DisplayChanges changes{};
1379 for (size_t i = 0; i < composition_types.size(); i++) {
1380 changes.AddLayerCompositionChange(display_id, changed_layers[i],
1381 composition_types[i]);
1382 }
1383
1384 std::vector<DisplayRequest::LayerRequest> layer_requests;
1385 for (size_t i = 0; i < requested_layers.size(); i++) {
1386 layer_requests.push_back({requested_layers[i], request_masks[i]});
1387 }
1388
1389 const DisplayRequest request_changes{display_id, display_request_mask,
1390 layer_requests};
1391 changes.display_request_changes = request_changes;
1392
1393 cmd_result_writer_->AddChanges(changes);
1394 composer_resources_->SetDisplayMustValidateState(display_id, false);
1395}
1396
1397void ComposerClient::ExecuteAcceptDisplayChanges(int64_t display_id) {
1398 auto* display = GetDisplay(display_id);
1399 if (display == nullptr) {
1400 cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
1401 return;
1402 }
1403
1404 auto error = Hwc2toHwc3Error(display->AcceptDisplayChanges());
1405 if (error != hwc3::Error::kNone) {
1406 cmd_result_writer_->AddError(error);
1407 return;
1408 }
1409}
1410
1411void ComposerClient::ExecutePresentDisplay(int64_t display_id) {
1412 auto* display = GetDisplay(display_id);
1413 if (display == nullptr) {
1414 cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
1415 return;
1416 }
1417
1418 ::android::base::unique_fd display_fence;
1419 std::unordered_map<int64_t, ::android::base::unique_fd> release_fences;
1420 auto error = PresentDisplayInternal(display_id, display_fence,
1421 release_fences);
1422 if (error != hwc3::Error::kNone) {
1423 cmd_result_writer_->AddError(error);
1424 }
1425 if (cmd_result_writer_->HasError()) {
1426 return;
1427 }
1428
1429 cmd_result_writer_->AddPresentFence(display_id, std::move(display_fence));
1430 cmd_result_writer_->AddReleaseFence(display_id, release_fences);
1431}
1432
1433void ComposerClient::ExecutePresentOrValidateDisplay(
1434 int64_t display_id,
1435 std::optional<ClockMonotonicTimestamp> expected_present_time) {
1436 auto* display = GetDisplay(display_id);
1437 if (display == nullptr) {
1438 cmd_result_writer_->AddError(hwc3::Error::kBadDisplay);
1439 return;
1440 }
1441
1442 /* TODO: Handle expectedPresentTime */
Normunds Rieksts42820952024-03-12 15:42:06 +00001443 /* This can be implemented in multiple ways. For example, the expected present
1444 * time property can be implemented by the DRM driver directly as a CRTC
1445 * property. See:
1446 * https://cs.android.com/android/platform/superproject/main/+/b8b3b1646e64d0235f77b9e717a3e4082e26f2a8:hardware/google/graphics/common/libhwc2.1/libdrmresource/drm/drmcrtc.cpp;drc=468f6172546ab98983de18210222f231f16b21e1;l=88
1447 * Unfortunately there doesn't seem to be a standardised way of delaying
1448 * presentation with a timestamp in the DRM API. What we can do alternatively
1449 * is to spawn a separate presentation thread that could handle the VBlank
1450 * events by using DRM_MODE_PAGE_FLIP_EVENT and schedule them appropriately.
1451 */
1452
Drew Davenport5951b112024-08-05 09:44:27 -06001453 /* TODO: Add check if it's possible to skip display validation */
1454 ExecuteValidateDisplay(display_id, expected_present_time);
1455 cmd_result_writer_
1456 ->AddPresentOrValidateResult(display_id,
1457 PresentOrValidate::Result::Validated);
1458}
1459
Dennis Tsiang33f0ece2023-11-29 12:45:04 +00001460} // namespace aidl::android::hardware::graphics::composer3::impl