blob: 49487557f74f9ee00cedcdb2d18c440976963626 [file] [log] [blame]
Roman Stratiienko3627beb2022-01-04 16:02:55 +02001/*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "hwc-display"
18#define ATRACE_TAG ATRACE_TAG_GRAPHICS
19
20#include "HwcDisplay.h"
21
22#include "DrmHwcTwo.h"
Roman Stratiienkobb594ba2022-02-18 16:52:03 +020023#include "backend/Backend.h"
Roman Stratiienko3627beb2022-01-04 16:02:55 +020024#include "backend/BackendManager.h"
25#include "bufferinfo/BufferInfoGetter.h"
26#include "utils/log.h"
27#include "utils/properties.h"
28
29namespace android {
30
31std::string HwcDisplay::DumpDelta(HwcDisplay::Stats delta) {
32 if (delta.total_pixops_ == 0)
33 return "No stats yet";
Roman Stratiienkoa7913de2022-10-20 13:18:57 +030034 auto ratio = 1.0 - double(delta.gpu_pixops_) / double(delta.total_pixops_);
Roman Stratiienko3627beb2022-01-04 16:02:55 +020035
36 std::stringstream ss;
37 ss << " Total frames count: " << delta.total_frames_ << "\n"
38 << " Failed to test commit frames: " << delta.failed_kms_validate_ << "\n"
39 << " Failed to commit frames: " << delta.failed_kms_present_ << "\n"
40 << ((delta.failed_kms_present_ > 0)
41 ? " !!! Internal failure, FIX it please\n"
42 : "")
43 << " Flattened frames: " << delta.frames_flattened_ << "\n"
44 << " Pixel operations (free units)"
45 << " : [TOTAL: " << delta.total_pixops_ << " / GPU: " << delta.gpu_pixops_
46 << "]\n"
47 << " Composition efficiency: " << ratio;
48
49 return ss.str();
50}
51
52std::string HwcDisplay::Dump() {
53 std::string flattening_state_str;
54 switch (flattenning_state_) {
55 case ClientFlattenningState::Disabled:
56 flattening_state_str = "Disabled";
57 break;
58 case ClientFlattenningState::NotRequired:
59 flattening_state_str = "Not needed";
60 break;
61 case ClientFlattenningState::Flattened:
62 flattening_state_str = "Active";
63 break;
64 case ClientFlattenningState::ClientRefreshRequested:
65 flattening_state_str = "Refresh requested";
66 break;
67 default:
68 flattening_state_str = std::to_string(flattenning_state_) +
69 " VSync remains";
70 }
71
Roman Stratiienkoa7913de2022-10-20 13:18:57 +030072 auto connector_name = IsInHeadlessMode()
73 ? std::string("NULL-DISPLAY")
74 : GetPipe().connector->Get()->GetName();
Roman Stratiienko19c162f2022-02-01 09:35:08 +020075
Roman Stratiienko3627beb2022-01-04 16:02:55 +020076 std::stringstream ss;
Roman Stratiienko19c162f2022-02-01 09:35:08 +020077 ss << "- Display on: " << connector_name << "\n"
Roman Stratiienko3627beb2022-01-04 16:02:55 +020078 << " Flattening state: " << flattening_state_str << "\n"
79 << "Statistics since system boot:\n"
80 << DumpDelta(total_stats_) << "\n\n"
81 << "Statistics since last dumpsys request:\n"
82 << DumpDelta(total_stats_.minus(prev_stats_)) << "\n\n";
83
84 memcpy(&prev_stats_, &total_stats_, sizeof(Stats));
85 return ss.str();
86}
87
Roman Stratiienkobb594ba2022-02-18 16:52:03 +020088HwcDisplay::HwcDisplay(hwc2_display_t handle, HWC2::DisplayType type,
89 DrmHwcTwo *hwc2)
Roman Stratiienko3627beb2022-01-04 16:02:55 +020090 : hwc2_(hwc2),
Roman Stratiienko3627beb2022-01-04 16:02:55 +020091 handle_(handle),
92 type_(type),
Roman Stratiienko4b2cc482022-02-21 14:53:58 +020093 client_layer_(this),
Roman Stratiienko3627beb2022-01-04 16:02:55 +020094 color_transform_hint_(HAL_COLOR_TRANSFORM_IDENTITY) {
95 // clang-format off
96 color_transform_matrix_ = {1.0, 0.0, 0.0, 0.0,
97 0.0, 1.0, 0.0, 0.0,
98 0.0, 0.0, 1.0, 0.0,
99 0.0, 0.0, 0.0, 1.0};
100 // clang-format on
Roman Stratiienko3dacd472022-01-11 19:18:34 +0200101}
102
Roman Stratiienkobb594ba2022-02-18 16:52:03 +0200103HwcDisplay::~HwcDisplay() = default;
Roman Stratiienko3dacd472022-01-11 19:18:34 +0200104
Roman Stratiienkobb594ba2022-02-18 16:52:03 +0200105void HwcDisplay::SetPipeline(DrmDisplayPipeline *pipeline) {
Roman Stratiienkod0494d92022-03-15 18:02:04 +0200106 Deinit();
107
Roman Stratiienkobb594ba2022-02-18 16:52:03 +0200108 pipeline_ = pipeline;
109
Roman Stratiienkod0494d92022-03-15 18:02:04 +0200110 if (pipeline != nullptr || handle_ == kPrimaryDisplay) {
Roman Stratiienkobb594ba2022-02-18 16:52:03 +0200111 Init();
Roman Stratiienkobb594ba2022-02-18 16:52:03 +0200112 hwc2_->ScheduleHotplugEvent(handle_, /*connected = */ true);
113 } else {
Roman Stratiienkod0494d92022-03-15 18:02:04 +0200114 hwc2_->ScheduleHotplugEvent(handle_, /*connected = */ false);
Roman Stratiienkobb594ba2022-02-18 16:52:03 +0200115 }
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200116}
117
Roman Stratiienkod0494d92022-03-15 18:02:04 +0200118void HwcDisplay::Deinit() {
119 if (pipeline_ != nullptr) {
120 AtomicCommitArgs a_args{};
Roman Stratiienkod0494d92022-03-15 18:02:04 +0200121 a_args.composition = std::make_shared<DrmKmsPlan>();
122 GetPipe().atomic_state_manager->ExecuteAtomicCommit(a_args);
John Stultz799e8c72022-06-30 19:49:42 +0000123/*
124 * TODO:
125 * Unfortunately the following causes regressions on db845c
126 * with VtsHalGraphicsComposerV2_3TargetTest due to the display
127 * never coming back. Patches to avoiding that issue on the
128 * the kernel side unfortunately causes further crashes in
129 * drm_hwcomposer, because the client detach takes longer then the
130 * 1 second max VTS expects. So for now as a workaround, lets skip
131 * deactivating the display on deinit, which matches previous
132 * behavior prior to commit d0494d9b8097
133 */
134#if 0
Roman Stratiienkoaf862a52022-06-22 12:14:22 +0300135 a_args.composition = {};
136 a_args.active = false;
137 GetPipe().atomic_state_manager->ExecuteAtomicCommit(a_args);
John Stultz799e8c72022-06-30 19:49:42 +0000138#endif
Roman Stratiienkod0494d92022-03-15 18:02:04 +0200139
Roman Stratiienkod0494d92022-03-15 18:02:04 +0200140 current_plan_.reset();
141 backend_.reset();
142 }
143
Roman Stratiienkod2cc7382022-12-28 18:51:59 +0200144 if (vsync_worker_) {
145 vsync_worker_->StopThread();
146 vsync_worker_ = {};
147 }
148
Roman Stratiienkod0494d92022-03-15 18:02:04 +0200149 SetClientTarget(nullptr, -1, 0, {});
150}
151
Roman Stratiienko19c162f2022-02-01 09:35:08 +0200152HWC2::Error HwcDisplay::Init() {
Roman Stratiienkod0494d92022-03-15 18:02:04 +0200153 ChosePreferredConfig();
154
Roman Stratiienkod2cc7382022-12-28 18:51:59 +0200155 auto vsw_callbacks = (VSyncWorkerCallbacks){
156 .out_event =
157 [this](int64_t timestamp) {
158 const std::lock_guard<std::mutex> lock(
159 hwc2_->GetResMan().GetMainLock());
160 if (vsync_event_en_) {
161 uint32_t period_ns{};
162 GetDisplayVsyncPeriod(&period_ns);
163 hwc2_->SendVsyncEventToClient(handle_, timestamp, period_ns);
164 }
165 if (vsync_flattening_en_) {
166 ProcessFlatenningVsyncInternal();
167 }
168 if (vsync_tracking_en_) {
169 last_vsync_ts_ = timestamp;
170 }
171 if (!vsync_event_en_ && !vsync_flattening_en_ &&
172 !vsync_tracking_en_) {
173 vsync_worker_->VSyncControl(false);
174 }
175 },
176 .get_vperiod_ns = [this]() -> uint32_t {
177 uint32_t outVsyncPeriod = 0;
178 GetDisplayVsyncPeriod(&outVsyncPeriod);
179 return outVsyncPeriod;
180 },
181 };
182
183 vsync_worker_ = VSyncWorker::CreateInstance(pipeline_, vsw_callbacks);
184 if (!vsync_worker_) {
185 ALOGE("Failed to create event worker for d=%d\n", int(handle_));
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200186 return HWC2::Error::BadDisplay;
187 }
188
Roman Stratiienko3dacd472022-01-11 19:18:34 +0200189 if (!IsInHeadlessMode()) {
Roman Stratiienkod2cc7382022-12-28 18:51:59 +0200190 auto ret = BackendManager::GetInstance().SetBackendForDisplay(this);
Roman Stratiienko3dacd472022-01-11 19:18:34 +0200191 if (ret) {
192 ALOGE("Failed to set backend for d=%d %d\n", int(handle_), ret);
193 return HWC2::Error::BadDisplay;
194 }
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200195 }
196
197 client_layer_.SetLayerBlendMode(HWC2_BLEND_MODE_PREMULTIPLIED);
198
Roman Stratiienko3dacd472022-01-11 19:18:34 +0200199 return HWC2::Error::None;
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200200}
201
202HWC2::Error HwcDisplay::ChosePreferredConfig() {
Roman Stratiienko3dacd472022-01-11 19:18:34 +0200203 HWC2::Error err{};
204 if (!IsInHeadlessMode()) {
205 err = configs_.Update(*pipeline_->connector->Get());
206 } else {
207 configs_.FillHeadless();
208 }
209 if (!IsInHeadlessMode() && err != HWC2::Error::None) {
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200210 return HWC2::Error::BadDisplay;
Roman Stratiienko3dacd472022-01-11 19:18:34 +0200211 }
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200212
Roman Stratiienko0137f862022-01-04 18:27:40 +0200213 return SetActiveConfig(configs_.preferred_config_id);
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200214}
215
216HWC2::Error HwcDisplay::AcceptDisplayChanges() {
217 for (std::pair<const hwc2_layer_t, HwcLayer> &l : layers_)
218 l.second.AcceptTypeChange();
219 return HWC2::Error::None;
220}
221
222HWC2::Error HwcDisplay::CreateLayer(hwc2_layer_t *layer) {
Roman Stratiienko4b2cc482022-02-21 14:53:58 +0200223 layers_.emplace(static_cast<hwc2_layer_t>(layer_idx_), HwcLayer(this));
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200224 *layer = static_cast<hwc2_layer_t>(layer_idx_);
225 ++layer_idx_;
226 return HWC2::Error::None;
227}
228
229HWC2::Error HwcDisplay::DestroyLayer(hwc2_layer_t layer) {
Roman Stratiienko3dacd472022-01-11 19:18:34 +0200230 if (!get_layer(layer)) {
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200231 return HWC2::Error::BadLayer;
Roman Stratiienko3dacd472022-01-11 19:18:34 +0200232 }
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200233
234 layers_.erase(layer);
235 return HWC2::Error::None;
236}
237
238HWC2::Error HwcDisplay::GetActiveConfig(hwc2_config_t *config) const {
Roman Stratiienkod0c035b2022-01-21 15:12:56 +0200239 if (configs_.hwc_configs.count(staged_mode_config_id_) == 0)
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200240 return HWC2::Error::BadConfig;
241
Roman Stratiienkod0c035b2022-01-21 15:12:56 +0200242 *config = staged_mode_config_id_;
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200243 return HWC2::Error::None;
244}
245
246HWC2::Error HwcDisplay::GetChangedCompositionTypes(uint32_t *num_elements,
247 hwc2_layer_t *layers,
248 int32_t *types) {
Roman Stratiienkof0c507f2022-01-17 18:29:24 +0200249 if (IsInHeadlessMode()) {
250 *num_elements = 0;
251 return HWC2::Error::None;
252 }
253
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200254 uint32_t num_changes = 0;
Roman Stratiienkoa7913de2022-10-20 13:18:57 +0300255 for (auto &l : layers_) {
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200256 if (l.second.IsTypeChanged()) {
257 if (layers && num_changes < *num_elements)
258 layers[num_changes] = l.first;
259 if (types && num_changes < *num_elements)
260 types[num_changes] = static_cast<int32_t>(l.second.GetValidatedType());
261 ++num_changes;
262 }
263 }
264 if (!layers && !types)
265 *num_elements = num_changes;
266 return HWC2::Error::None;
267}
268
269HWC2::Error HwcDisplay::GetClientTargetSupport(uint32_t width, uint32_t height,
270 int32_t /*format*/,
271 int32_t dataspace) {
Roman Stratiienkof0c507f2022-01-17 18:29:24 +0200272 if (IsInHeadlessMode()) {
273 return HWC2::Error::None;
274 }
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200275
Roman Stratiienkoa7913de2022-10-20 13:18:57 +0300276 auto min = pipeline_->device->GetMinResolution();
277 auto max = pipeline_->device->GetMaxResolution();
Roman Stratiienko3dacd472022-01-11 19:18:34 +0200278
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200279 if (width < min.first || height < min.second)
280 return HWC2::Error::Unsupported;
281
282 if (width > max.first || height > max.second)
283 return HWC2::Error::Unsupported;
284
285 if (dataspace != HAL_DATASPACE_UNKNOWN)
286 return HWC2::Error::Unsupported;
287
288 // TODO(nobody): Validate format can be handled by either GL or planes
289 return HWC2::Error::None;
290}
291
292HWC2::Error HwcDisplay::GetColorModes(uint32_t *num_modes, int32_t *modes) {
293 if (!modes)
294 *num_modes = 1;
295
296 if (modes)
297 *modes = HAL_COLOR_MODE_NATIVE;
298
299 return HWC2::Error::None;
300}
301
302HWC2::Error HwcDisplay::GetDisplayAttribute(hwc2_config_t config,
303 int32_t attribute_in,
304 int32_t *value) {
305 int conf = static_cast<int>(config);
306
Roman Stratiienko0137f862022-01-04 18:27:40 +0200307 if (configs_.hwc_configs.count(conf) == 0) {
Roman Stratiienko3dacd472022-01-11 19:18:34 +0200308 ALOGE("Could not find mode #%d", conf);
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200309 return HWC2::Error::BadConfig;
310 }
311
Roman Stratiienko0137f862022-01-04 18:27:40 +0200312 auto &hwc_config = configs_.hwc_configs[conf];
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200313
314 static const int32_t kUmPerInch = 25400;
Roman Stratiienkoa7913de2022-10-20 13:18:57 +0300315 auto mm_width = configs_.mm_width;
316 auto mm_height = configs_.mm_height;
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200317 auto attribute = static_cast<HWC2::Attribute>(attribute_in);
318 switch (attribute) {
319 case HWC2::Attribute::Width:
Roman Stratiienkodf3120f2022-12-07 23:10:55 +0200320 *value = static_cast<int>(hwc_config.mode.GetRawMode().hdisplay);
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200321 break;
322 case HWC2::Attribute::Height:
Roman Stratiienkodf3120f2022-12-07 23:10:55 +0200323 *value = static_cast<int>(hwc_config.mode.GetRawMode().vdisplay);
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200324 break;
325 case HWC2::Attribute::VsyncPeriod:
326 // in nanoseconds
Roman Stratiienkodf3120f2022-12-07 23:10:55 +0200327 *value = static_cast<int>(1E9 / hwc_config.mode.GetVRefresh());
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200328 break;
329 case HWC2::Attribute::DpiX:
330 // Dots per 1000 inches
Roman Stratiienkodf3120f2022-12-07 23:10:55 +0200331 *value = mm_width ? int(hwc_config.mode.GetRawMode().hdisplay *
332 kUmPerInch / mm_width)
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200333 : -1;
334 break;
335 case HWC2::Attribute::DpiY:
336 // Dots per 1000 inches
Roman Stratiienkodf3120f2022-12-07 23:10:55 +0200337 *value = mm_height ? int(hwc_config.mode.GetRawMode().vdisplay *
338 kUmPerInch / mm_height)
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200339 : -1;
340 break;
Roman Stratiienko6b405052022-12-10 19:09:10 +0200341#if __ANDROID_API__ > 29
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200342 case HWC2::Attribute::ConfigGroup:
343 /* Dispite ConfigGroup is a part of HWC2.4 API, framework
344 * able to request it even if service @2.1 is used */
Roman Stratiienkod0c035b2022-01-21 15:12:56 +0200345 *value = int(hwc_config.group_id);
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200346 break;
347#endif
348 default:
349 *value = -1;
350 return HWC2::Error::BadConfig;
351 }
352 return HWC2::Error::None;
353}
354
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200355HWC2::Error HwcDisplay::GetDisplayConfigs(uint32_t *num_configs,
356 hwc2_config_t *configs) {
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200357 uint32_t idx = 0;
Roman Stratiienko0137f862022-01-04 18:27:40 +0200358 for (auto &hwc_config : configs_.hwc_configs) {
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200359 if (hwc_config.second.disabled) {
360 continue;
361 }
362
363 if (configs != nullptr) {
364 if (idx >= *num_configs) {
365 break;
366 }
367 configs[idx] = hwc_config.second.id;
368 }
369
370 idx++;
371 }
372 *num_configs = idx;
373 return HWC2::Error::None;
374}
375
376HWC2::Error HwcDisplay::GetDisplayName(uint32_t *size, char *name) {
377 std::ostringstream stream;
Roman Stratiienko3dacd472022-01-11 19:18:34 +0200378 if (IsInHeadlessMode()) {
379 stream << "null-display";
380 } else {
381 stream << "display-" << GetPipe().connector->Get()->GetId();
382 }
Roman Stratiienkoa7913de2022-10-20 13:18:57 +0300383 auto string = stream.str();
384 auto length = string.length();
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200385 if (!name) {
386 *size = length;
387 return HWC2::Error::None;
388 }
389
390 *size = std::min<uint32_t>(static_cast<uint32_t>(length - 1), *size);
391 strncpy(name, string.c_str(), *size);
392 return HWC2::Error::None;
393}
394
395HWC2::Error HwcDisplay::GetDisplayRequests(int32_t * /*display_requests*/,
396 uint32_t *num_elements,
397 hwc2_layer_t * /*layers*/,
398 int32_t * /*layer_requests*/) {
399 // TODO(nobody): I think virtual display should request
400 // HWC2_DISPLAY_REQUEST_WRITE_CLIENT_TARGET_TO_OUTPUT here
401 *num_elements = 0;
402 return HWC2::Error::None;
403}
404
405HWC2::Error HwcDisplay::GetDisplayType(int32_t *type) {
406 *type = static_cast<int32_t>(type_);
407 return HWC2::Error::None;
408}
409
410HWC2::Error HwcDisplay::GetDozeSupport(int32_t *support) {
411 *support = 0;
412 return HWC2::Error::None;
413}
414
415HWC2::Error HwcDisplay::GetHdrCapabilities(uint32_t *num_types,
416 int32_t * /*types*/,
417 float * /*max_luminance*/,
418 float * /*max_average_luminance*/,
419 float * /*min_luminance*/) {
420 *num_types = 0;
421 return HWC2::Error::None;
422}
423
424/* Find API details at:
425 * https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=1767
Roman Stratiienkodd214942022-05-03 18:24:49 +0300426 *
427 * Called after PresentDisplay(), CLIENT is expecting release fence for the
428 * prior buffer (not the one assigned to the layer at the moment).
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200429 */
430HWC2::Error HwcDisplay::GetReleaseFences(uint32_t *num_elements,
431 hwc2_layer_t *layers,
432 int32_t *fences) {
Roman Stratiienkof0c507f2022-01-17 18:29:24 +0200433 if (IsInHeadlessMode()) {
434 *num_elements = 0;
435 return HWC2::Error::None;
436 }
437
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200438 uint32_t num_layers = 0;
439
Roman Stratiienkodd214942022-05-03 18:24:49 +0300440 for (auto &l : layers_) {
441 if (!l.second.GetPriorBufferScanOutFlag() || !present_fence_) {
442 continue;
443 }
444
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200445 ++num_layers;
Roman Stratiienkodd214942022-05-03 18:24:49 +0300446
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200447 if (layers == nullptr || fences == nullptr)
448 continue;
449
450 if (num_layers > *num_elements) {
451 ALOGW("Overflow num_elements %d/%d", num_layers, *num_elements);
452 return HWC2::Error::None;
453 }
454
455 layers[num_layers - 1] = l.first;
Roman Stratiienkodd214942022-05-03 18:24:49 +0300456 fences[num_layers - 1] = UniqueFd::Dup(present_fence_.Get()).Release();
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200457 }
458 *num_elements = num_layers;
Roman Stratiienkodd214942022-05-03 18:24:49 +0300459
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200460 return HWC2::Error::None;
461}
462
463HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) {
Roman Stratiienkof0c507f2022-01-17 18:29:24 +0200464 if (IsInHeadlessMode()) {
465 ALOGE("%s: Display is in headless mode, should never reach here", __func__);
466 return HWC2::Error::None;
467 }
468
Roman Stratiienkod2cc7382022-12-28 18:51:59 +0200469 uint32_t prev_vperiod_ns = 0;
470 GetDisplayVsyncPeriod(&prev_vperiod_ns);
Roman Stratiienkod0c035b2022-01-21 15:12:56 +0200471
472 auto mode_update_commited_ = false;
473 if (staged_mode_ &&
474 staged_mode_change_time_ <= ResourceManager::GetTimeMonotonicNs()) {
475 client_layer_.SetLayerDisplayFrame(
476 (hwc_rect_t){.left = 0,
477 .top = 0,
Roman Stratiienkodf3120f2022-12-07 23:10:55 +0200478 .right = int(staged_mode_->GetRawMode().hdisplay),
479 .bottom = int(staged_mode_->GetRawMode().vdisplay)});
Roman Stratiienkod0c035b2022-01-21 15:12:56 +0200480
481 configs_.active_config_id = staged_mode_config_id_;
482
483 a_args.display_mode = *staged_mode_;
484 if (!a_args.test_only) {
485 mode_update_commited_ = true;
486 }
487 }
488
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200489 // order the layers by z-order
490 bool use_client_layer = false;
491 uint32_t client_z_order = UINT32_MAX;
492 std::map<uint32_t, HwcLayer *> z_map;
493 for (std::pair<const hwc2_layer_t, HwcLayer> &l : layers_) {
494 switch (l.second.GetValidatedType()) {
495 case HWC2::Composition::Device:
Roman Stratiienkoa7913de2022-10-20 13:18:57 +0300496 z_map.emplace(l.second.GetZOrder(), &l.second);
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200497 break;
498 case HWC2::Composition::Client:
499 // Place it at the z_order of the lowest client layer
500 use_client_layer = true;
501 client_z_order = std::min(client_z_order, l.second.GetZOrder());
502 break;
503 default:
504 continue;
505 }
506 }
507 if (use_client_layer)
Roman Stratiienkoa7913de2022-10-20 13:18:57 +0300508 z_map.emplace(client_z_order, &client_layer_);
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200509
510 if (z_map.empty())
511 return HWC2::Error::BadLayer;
512
Roman Stratiienko4b2cc482022-02-21 14:53:58 +0200513 std::vector<LayerData> composition_layers;
514
515 /* Import & populate */
516 for (std::pair<const uint32_t, HwcLayer *> &l : z_map) {
517 l.second->PopulateLayerData(a_args.test_only);
518 }
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200519
520 // now that they're ordered by z, add them to the composition
521 for (std::pair<const uint32_t, HwcLayer *> &l : z_map) {
Roman Stratiienko4b2cc482022-02-21 14:53:58 +0200522 if (!l.second->IsLayerUsableAsDevice()) {
523 /* This will be normally triggered on validation of the first frame
524 * containing CLIENT layer. At this moment client buffer is not yet
525 * provided by the CLIENT.
526 * This may be triggered once in HwcLayer lifecycle in case FB can't be
527 * imported. For example when non-contiguous buffer is imported into
528 * contiguous-only DRM/KMS driver.
529 */
530 return HWC2::Error::BadLayer;
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200531 }
Roman Stratiienko4b2cc482022-02-21 14:53:58 +0200532 composition_layers.emplace_back(l.second->GetLayerData().Clone());
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200533 }
534
Roman Stratiienko9362cef2022-02-02 09:53:50 +0200535 /* Store plan to ensure shared planes won't be stolen by other display
536 * in between of ValidateDisplay() and PresentDisplay() calls
537 */
538 current_plan_ = DrmKmsPlan::CreateDrmKmsPlan(GetPipe(),
539 std::move(composition_layers));
540 if (!current_plan_) {
541 if (!a_args.test_only) {
542 ALOGE("Failed to create DrmKmsPlan");
543 }
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200544 return HWC2::Error::BadConfig;
545 }
546
Roman Stratiienko9362cef2022-02-02 09:53:50 +0200547 a_args.composition = current_plan_;
548
Roman Stratiienkoa7913de2022-10-20 13:18:57 +0300549 auto ret = GetPipe().atomic_state_manager->ExecuteAtomicCommit(a_args);
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200550
551 if (ret) {
552 if (!a_args.test_only)
553 ALOGE("Failed to apply the frame composition ret=%d", ret);
554 return HWC2::Error::BadParameter;
555 }
556
Roman Stratiienkod0c035b2022-01-21 15:12:56 +0200557 if (mode_update_commited_) {
558 staged_mode_.reset();
559 vsync_tracking_en_ = false;
560 if (last_vsync_ts_ != 0) {
Roman Stratiienkod2cc7382022-12-28 18:51:59 +0200561 hwc2_->SendVsyncPeriodTimingChangedEventToClient(handle_,
562 last_vsync_ts_ +
563 prev_vperiod_ns);
Roman Stratiienkod0c035b2022-01-21 15:12:56 +0200564 }
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200565 }
566
567 return HWC2::Error::None;
568}
569
570/* Find API details at:
571 * https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=1805
572 */
Roman Stratiienkodd214942022-05-03 18:24:49 +0300573HWC2::Error HwcDisplay::PresentDisplay(int32_t *out_present_fence) {
Roman Stratiienkof0c507f2022-01-17 18:29:24 +0200574 if (IsInHeadlessMode()) {
Roman Stratiienkodd214942022-05-03 18:24:49 +0300575 *out_present_fence = -1;
Roman Stratiienkof0c507f2022-01-17 18:29:24 +0200576 return HWC2::Error::None;
577 }
Roman Stratiienko780f7da2022-01-10 16:04:15 +0200578 HWC2::Error ret{};
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200579
580 ++total_stats_.total_frames_;
581
582 AtomicCommitArgs a_args{};
583 ret = CreateComposition(a_args);
584
585 if (ret != HWC2::Error::None)
586 ++total_stats_.failed_kms_present_;
587
588 if (ret == HWC2::Error::BadLayer) {
589 // Can we really have no client or device layers?
Roman Stratiienkodd214942022-05-03 18:24:49 +0300590 *out_present_fence = -1;
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200591 return HWC2::Error::None;
592 }
593 if (ret != HWC2::Error::None)
594 return ret;
595
Roman Stratiienkodd214942022-05-03 18:24:49 +0300596 this->present_fence_ = UniqueFd::Dup(a_args.out_fence.Get());
597 *out_present_fence = a_args.out_fence.Release();
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200598
599 ++frame_no_;
600 return HWC2::Error::None;
601}
602
Roman Stratiienkod0c035b2022-01-21 15:12:56 +0200603HWC2::Error HwcDisplay::SetActiveConfigInternal(uint32_t config,
604 int64_t change_time) {
605 if (configs_.hwc_configs.count(config) == 0) {
606 ALOGE("Could not find active mode for %u", config);
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200607 return HWC2::Error::BadConfig;
608 }
609
Roman Stratiienkod0c035b2022-01-21 15:12:56 +0200610 staged_mode_ = configs_.hwc_configs[config].mode;
611 staged_mode_change_time_ = change_time;
612 staged_mode_config_id_ = config;
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200613
614 return HWC2::Error::None;
615}
616
Roman Stratiienkod0c035b2022-01-21 15:12:56 +0200617HWC2::Error HwcDisplay::SetActiveConfig(hwc2_config_t config) {
618 return SetActiveConfigInternal(config, ResourceManager::GetTimeMonotonicNs());
619}
620
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200621/* Find API details at:
622 * https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=1861
623 */
624HWC2::Error HwcDisplay::SetClientTarget(buffer_handle_t target,
625 int32_t acquire_fence,
626 int32_t dataspace,
627 hwc_region_t /*damage*/) {
628 client_layer_.SetLayerBuffer(target, acquire_fence);
629 client_layer_.SetLayerDataspace(dataspace);
630
631 /*
632 * target can be nullptr, this does mean the Composer Service is calling
633 * cleanDisplayResources() on after receiving HOTPLUG event. See more at:
634 * https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h;l=350;drc=944b68180b008456ed2eb4d4d329e33b19bd5166
635 */
636 if (target == nullptr) {
Roman Stratiienkoa32f9072022-05-13 12:12:20 +0300637 client_layer_.SwChainClearCache();
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200638 return HWC2::Error::None;
639 }
640
Roman Stratiienko5070d512022-05-30 13:41:20 +0300641 if (IsInHeadlessMode()) {
642 return HWC2::Error::None;
643 }
644
Roman Stratiienko4b2cc482022-02-21 14:53:58 +0200645 client_layer_.PopulateLayerData(/*test = */ true);
646 if (!client_layer_.IsLayerUsableAsDevice()) {
647 ALOGE("Client layer must be always usable by DRM/KMS");
648 return HWC2::Error::BadLayer;
Roman Stratiienkoe9fbd8d2022-02-21 13:03:29 +0200649 }
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200650
Roman Stratiienko4b2cc482022-02-21 14:53:58 +0200651 auto &bi = client_layer_.GetLayerData().bi;
Roman Stratiienkoa7913de2022-10-20 13:18:57 +0300652 if (!bi) {
653 ALOGE("%s: Invalid state", __func__);
654 return HWC2::Error::BadLayer;
655 }
656
657 auto source_crop = (hwc_frect_t){.left = 0.0F,
658 .top = 0.0F,
659 .right = static_cast<float>(bi->width),
660 .bottom = static_cast<float>(bi->height)};
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200661 client_layer_.SetLayerSourceCrop(source_crop);
662
663 return HWC2::Error::None;
664}
665
666HWC2::Error HwcDisplay::SetColorMode(int32_t mode) {
667 if (mode < HAL_COLOR_MODE_NATIVE || mode > HAL_COLOR_MODE_BT2100_HLG)
668 return HWC2::Error::BadParameter;
669
670 if (mode != HAL_COLOR_MODE_NATIVE)
671 return HWC2::Error::Unsupported;
672
673 color_mode_ = mode;
674 return HWC2::Error::None;
675}
676
677HWC2::Error HwcDisplay::SetColorTransform(const float *matrix, int32_t hint) {
678 if (hint < HAL_COLOR_TRANSFORM_IDENTITY ||
679 hint > HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA)
680 return HWC2::Error::BadParameter;
681
682 if (!matrix && hint == HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX)
683 return HWC2::Error::BadParameter;
684
685 color_transform_hint_ = static_cast<android_color_transform_t>(hint);
686 if (color_transform_hint_ == HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX)
687 std::copy(matrix, matrix + MATRIX_SIZE, color_transform_matrix_.begin());
688
689 return HWC2::Error::None;
690}
691
692HWC2::Error HwcDisplay::SetOutputBuffer(buffer_handle_t /*buffer*/,
693 int32_t /*release_fence*/) {
694 // TODO(nobody): Need virtual display support
695 return HWC2::Error::Unsupported;
696}
697
698HWC2::Error HwcDisplay::SetPowerMode(int32_t mode_in) {
699 auto mode = static_cast<HWC2::PowerMode>(mode_in);
Roman Stratiienkoccaf5162022-04-01 19:26:30 +0300700
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200701 AtomicCommitArgs a_args{};
702
703 switch (mode) {
704 case HWC2::PowerMode::Off:
705 a_args.active = false;
706 break;
707 case HWC2::PowerMode::On:
Roman Stratiienkoccaf5162022-04-01 19:26:30 +0300708 a_args.active = true;
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200709 break;
710 case HWC2::PowerMode::Doze:
711 case HWC2::PowerMode::DozeSuspend:
712 return HWC2::Error::Unsupported;
713 default:
Roman Stratiienkoccaf5162022-04-01 19:26:30 +0300714 ALOGE("Incorrect power mode value (%d)\n", mode);
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200715 return HWC2::Error::BadParameter;
Roman Stratiienkoccaf5162022-04-01 19:26:30 +0300716 }
717
718 if (IsInHeadlessMode()) {
719 return HWC2::Error::None;
720 }
721
Jia Ren80566fe2022-11-17 17:26:00 +0800722 if (a_args.active && *a_args.active) {
Roman Stratiienkoccaf5162022-04-01 19:26:30 +0300723 /*
724 * Setting the display to active before we have a composition
725 * can break some drivers, so skip setting a_args.active to
726 * true, as the next composition frame will implicitly activate
727 * the display
728 */
729 return GetPipe().atomic_state_manager->ActivateDisplayUsingDPMS() == 0
730 ? HWC2::Error::None
731 : HWC2::Error::BadParameter;
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200732 };
733
Roman Stratiienkoa7913de2022-10-20 13:18:57 +0300734 auto err = GetPipe().atomic_state_manager->ExecuteAtomicCommit(a_args);
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200735 if (err) {
736 ALOGE("Failed to apply the dpms composition err=%d", err);
737 return HWC2::Error::BadParameter;
738 }
739 return HWC2::Error::None;
740}
741
742HWC2::Error HwcDisplay::SetVsyncEnabled(int32_t enabled) {
Roman Stratiienko099c3112022-01-20 11:50:54 +0200743 vsync_event_en_ = HWC2_VSYNC_ENABLE == enabled;
744 if (vsync_event_en_) {
Roman Stratiienkod2cc7382022-12-28 18:51:59 +0200745 vsync_worker_->VSyncControl(true);
Roman Stratiienko099c3112022-01-20 11:50:54 +0200746 }
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200747 return HWC2::Error::None;
748}
749
750HWC2::Error HwcDisplay::ValidateDisplay(uint32_t *num_types,
751 uint32_t *num_requests) {
Roman Stratiienkof0c507f2022-01-17 18:29:24 +0200752 if (IsInHeadlessMode()) {
753 *num_types = *num_requests = 0;
754 return HWC2::Error::None;
755 }
Roman Stratiienkodd214942022-05-03 18:24:49 +0300756
757 /* In current drm_hwc design in case previous frame layer was not validated as
758 * a CLIENT, it is used by display controller (Front buffer). We have to store
759 * this state to provide the CLIENT with the release fences for such buffers.
760 */
761 for (auto &l : layers_) {
762 l.second.SetPriorBufferScanOutFlag(l.second.GetValidatedType() !=
763 HWC2::Composition::Client);
764 }
765
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200766 return backend_->ValidateDisplay(this, num_types, num_requests);
767}
768
769std::vector<HwcLayer *> HwcDisplay::GetOrderLayersByZPos() {
770 std::vector<HwcLayer *> ordered_layers;
771 ordered_layers.reserve(layers_.size());
772
773 for (auto &[handle, layer] : layers_) {
774 ordered_layers.emplace_back(&layer);
775 }
776
777 std::sort(std::begin(ordered_layers), std::end(ordered_layers),
778 [](const HwcLayer *lhs, const HwcLayer *rhs) {
779 return lhs->GetZOrder() < rhs->GetZOrder();
780 });
781
782 return ordered_layers;
783}
784
Roman Stratiienko099c3112022-01-20 11:50:54 +0200785HWC2::Error HwcDisplay::GetDisplayVsyncPeriod(
786 uint32_t *outVsyncPeriod /* ns */) {
787 return GetDisplayAttribute(configs_.active_config_id,
788 HWC2_ATTRIBUTE_VSYNC_PERIOD,
789 (int32_t *)(outVsyncPeriod));
790}
791
Roman Stratiienko6b405052022-12-10 19:09:10 +0200792#if __ANDROID_API__ > 29
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200793HWC2::Error HwcDisplay::GetDisplayConnectionType(uint32_t *outType) {
Roman Stratiienko456e2d62022-01-29 01:17:39 +0200794 if (IsInHeadlessMode()) {
795 *outType = static_cast<uint32_t>(HWC2::DisplayConnectionType::Internal);
796 return HWC2::Error::None;
797 }
798 /* Primary display should be always internal,
799 * otherwise SF will be unhappy and will crash
800 */
Roman Stratiienko19c162f2022-02-01 09:35:08 +0200801 if (GetPipe().connector->Get()->IsInternal() || handle_ == kPrimaryDisplay)
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200802 *outType = static_cast<uint32_t>(HWC2::DisplayConnectionType::Internal);
Roman Stratiienko19c162f2022-02-01 09:35:08 +0200803 else if (GetPipe().connector->Get()->IsExternal())
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200804 *outType = static_cast<uint32_t>(HWC2::DisplayConnectionType::External);
805 else
806 return HWC2::Error::BadConfig;
807
808 return HWC2::Error::None;
809}
810
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200811HWC2::Error HwcDisplay::SetActiveConfigWithConstraints(
Roman Stratiienkod0c035b2022-01-21 15:12:56 +0200812 hwc2_config_t config,
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200813 hwc_vsync_period_change_constraints_t *vsyncPeriodChangeConstraints,
814 hwc_vsync_period_change_timeline_t *outTimeline) {
815 if (vsyncPeriodChangeConstraints == nullptr || outTimeline == nullptr) {
816 return HWC2::Error::BadParameter;
817 }
818
Roman Stratiienkod0c035b2022-01-21 15:12:56 +0200819 uint32_t current_vsync_period{};
820 GetDisplayVsyncPeriod(&current_vsync_period);
821
822 if (vsyncPeriodChangeConstraints->seamlessRequired) {
823 return HWC2::Error::SeamlessNotAllowed;
824 }
825
826 outTimeline->refreshTimeNanos = vsyncPeriodChangeConstraints
827 ->desiredTimeNanos -
828 current_vsync_period;
829 auto ret = SetActiveConfigInternal(config, outTimeline->refreshTimeNanos);
830 if (ret != HWC2::Error::None) {
831 return ret;
832 }
833
834 outTimeline->refreshRequired = true;
835 outTimeline->newVsyncAppliedTimeNanos = vsyncPeriodChangeConstraints
836 ->desiredTimeNanos;
837
838 last_vsync_ts_ = 0;
839 vsync_tracking_en_ = true;
Roman Stratiienkod2cc7382022-12-28 18:51:59 +0200840 vsync_worker_->VSyncControl(true);
Roman Stratiienkod0c035b2022-01-21 15:12:56 +0200841
842 return HWC2::Error::None;
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200843}
844
845HWC2::Error HwcDisplay::SetAutoLowLatencyMode(bool /*on*/) {
846 return HWC2::Error::Unsupported;
847}
848
849HWC2::Error HwcDisplay::GetSupportedContentTypes(
850 uint32_t *outNumSupportedContentTypes,
851 const uint32_t *outSupportedContentTypes) {
852 if (outSupportedContentTypes == nullptr)
853 *outNumSupportedContentTypes = 0;
854
855 return HWC2::Error::None;
856}
857
858HWC2::Error HwcDisplay::SetContentType(int32_t contentType) {
859 if (contentType != HWC2_CONTENT_TYPE_NONE)
860 return HWC2::Error::Unsupported;
861
862 /* TODO: Map to the DRM Connector property:
863 * https://elixir.bootlin.com/linux/v5.4-rc5/source/drivers/gpu/drm/drm_connector.c#L809
864 */
865
866 return HWC2::Error::None;
867}
868#endif
869
Roman Stratiienko6b405052022-12-10 19:09:10 +0200870#if __ANDROID_API__ > 28
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200871HWC2::Error HwcDisplay::GetDisplayIdentificationData(uint8_t *outPort,
872 uint32_t *outDataSize,
873 uint8_t *outData) {
Roman Stratiienko3dacd472022-01-11 19:18:34 +0200874 if (IsInHeadlessMode()) {
Roman Stratiienkof87d8082022-05-06 11:33:56 +0300875 return HWC2::Error::Unsupported;
Roman Stratiienko3dacd472022-01-11 19:18:34 +0200876 }
Roman Stratiienkof87d8082022-05-06 11:33:56 +0300877
Roman Stratiienko19c162f2022-02-01 09:35:08 +0200878 auto blob = GetPipe().connector->Get()->GetEdidBlob();
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200879 if (!blob) {
Roman Stratiienkof87d8082022-05-06 11:33:56 +0300880 return HWC2::Error::Unsupported;
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200881 }
882
Roman Stratiienkof87d8082022-05-06 11:33:56 +0300883 *outPort = handle_; /* TDOD(nobody): What should be here? */
884
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200885 if (outData) {
886 *outDataSize = std::min(*outDataSize, blob->length);
887 memcpy(outData, blob->data, *outDataSize);
888 } else {
889 *outDataSize = blob->length;
890 }
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200891
892 return HWC2::Error::None;
893}
894
895HWC2::Error HwcDisplay::GetDisplayCapabilities(uint32_t *outNumCapabilities,
896 uint32_t * /*outCapabilities*/) {
897 if (outNumCapabilities == nullptr) {
898 return HWC2::Error::BadParameter;
899 }
900
901 *outNumCapabilities = 0;
902
903 return HWC2::Error::None;
904}
905
906HWC2::Error HwcDisplay::GetDisplayBrightnessSupport(bool *supported) {
907 *supported = false;
908 return HWC2::Error::None;
909}
910
911HWC2::Error HwcDisplay::SetDisplayBrightness(float /* brightness */) {
912 return HWC2::Error::Unsupported;
913}
914
Roman Stratiienko6b405052022-12-10 19:09:10 +0200915#endif /* __ANDROID_API__ > 28 */
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200916
Roman Stratiienko6b405052022-12-10 19:09:10 +0200917#if __ANDROID_API__ > 27
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200918
919HWC2::Error HwcDisplay::GetRenderIntents(
920 int32_t mode, uint32_t *outNumIntents,
921 int32_t * /*android_render_intent_v1_1_t*/ outIntents) {
922 if (mode != HAL_COLOR_MODE_NATIVE) {
923 return HWC2::Error::BadParameter;
924 }
925
926 if (outIntents == nullptr) {
927 *outNumIntents = 1;
928 return HWC2::Error::None;
929 }
930 *outNumIntents = 1;
931 outIntents[0] = HAL_RENDER_INTENT_COLORIMETRIC;
932 return HWC2::Error::None;
933}
934
935HWC2::Error HwcDisplay::SetColorModeWithIntent(int32_t mode, int32_t intent) {
936 if (intent < HAL_RENDER_INTENT_COLORIMETRIC ||
937 intent > HAL_RENDER_INTENT_TONE_MAP_ENHANCE)
938 return HWC2::Error::BadParameter;
939
940 if (mode < HAL_COLOR_MODE_NATIVE || mode > HAL_COLOR_MODE_BT2100_HLG)
941 return HWC2::Error::BadParameter;
942
943 if (mode != HAL_COLOR_MODE_NATIVE)
944 return HWC2::Error::Unsupported;
945
946 if (intent != HAL_RENDER_INTENT_COLORIMETRIC)
947 return HWC2::Error::Unsupported;
948
949 color_mode_ = mode;
950 return HWC2::Error::None;
951}
952
Roman Stratiienko6b405052022-12-10 19:09:10 +0200953#endif /* __ANDROID_API__ > 27 */
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200954
955const Backend *HwcDisplay::backend() const {
956 return backend_.get();
957}
958
959void HwcDisplay::set_backend(std::unique_ptr<Backend> backend) {
960 backend_ = std::move(backend);
961}
962
Roman Stratiienko099c3112022-01-20 11:50:54 +0200963/* returns true if composition should be sent to client */
964bool HwcDisplay::ProcessClientFlatteningState(bool skip) {
Roman Stratiienkoa7913de2022-10-20 13:18:57 +0300965 const int flattenning_state = flattenning_state_;
Roman Stratiienko099c3112022-01-20 11:50:54 +0200966 if (flattenning_state == ClientFlattenningState::Disabled) {
967 return false;
968 }
969
970 if (skip) {
971 flattenning_state_ = ClientFlattenningState::NotRequired;
972 return false;
973 }
974
975 if (flattenning_state == ClientFlattenningState::ClientRefreshRequested) {
976 flattenning_state_ = ClientFlattenningState::Flattened;
977 return true;
978 }
979
980 vsync_flattening_en_ = true;
Roman Stratiienkod2cc7382022-12-28 18:51:59 +0200981 vsync_worker_->VSyncControl(true);
Roman Stratiienko099c3112022-01-20 11:50:54 +0200982 flattenning_state_ = ClientFlattenningState::VsyncCountdownMax;
983 return false;
984}
985
986void HwcDisplay::ProcessFlatenningVsyncInternal() {
987 if (flattenning_state_ > ClientFlattenningState::ClientRefreshRequested &&
988 --flattenning_state_ == ClientFlattenningState::ClientRefreshRequested &&
989 hwc2_->refresh_callback_.first != nullptr &&
990 hwc2_->refresh_callback_.second != nullptr) {
991 hwc2_->refresh_callback_.first(hwc2_->refresh_callback_.second, handle_);
992 vsync_flattening_en_ = false;
993 }
994}
995
Roman Stratiienko3627beb2022-01-04 16:02:55 +0200996} // namespace android