1 /*
2 * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of The Linux Foundation. nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include <core/buffer_allocator.h>
31 #include <utils/debug.h>
32 #include <utils/constants.h>
33 #include <sync/sync.h>
34 #include <vector>
35 #include <string>
36
37 #include "hwc_buffer_sync_handler.h"
38 #include "hwc_session.h"
39 #include "hwc_debugger.h"
40
41 #define __CLASS__ "HWCSession"
42
43 namespace sdm {
44
StartServices()45 void HWCSession::StartServices() {
46 int error = DisplayConfig::DeviceInterface::RegisterDevice(this);
47 if (error) {
48 DLOGW("Could not register IDisplayConfig as service (%d).", error);
49 } else {
50 DLOGI("IDisplayConfig service registration completed.");
51 }
52 }
53
MapDisplayType(DispType dpy)54 int MapDisplayType(DispType dpy) {
55 switch (dpy) {
56 case DispType::kPrimary:
57 return qdutils::DISPLAY_PRIMARY;
58
59 case DispType::kExternal:
60 return qdutils::DISPLAY_EXTERNAL;
61
62 case DispType::kVirtual:
63 return qdutils::DISPLAY_VIRTUAL;
64
65 default:
66 break;
67 }
68
69 return -EINVAL;
70 }
71
WaitForResourceNeeded(HWC2::PowerMode prev_mode,HWC2::PowerMode new_mode)72 bool WaitForResourceNeeded(HWC2::PowerMode prev_mode, HWC2::PowerMode new_mode) {
73 return ((prev_mode == HWC2::PowerMode::Off) &&
74 (new_mode == HWC2::PowerMode::On || new_mode == HWC2::PowerMode::Doze));
75 }
76
MapExternalStatus(DisplayConfig::ExternalStatus status)77 HWCDisplay::DisplayStatus MapExternalStatus(DisplayConfig::ExternalStatus status) {
78 switch (status) {
79 case DisplayConfig::ExternalStatus::kOffline:
80 return HWCDisplay::kDisplayStatusOffline;
81
82 case DisplayConfig::ExternalStatus::kOnline:
83 return HWCDisplay::kDisplayStatusOnline;
84
85 case DisplayConfig::ExternalStatus::kPause:
86 return HWCDisplay::kDisplayStatusPause;
87
88 case DisplayConfig::ExternalStatus::kResume:
89 return HWCDisplay::kDisplayStatusResume;
90
91 default:
92 break;
93 }
94
95 return HWCDisplay::kDisplayStatusInvalid;
96 }
97
RegisterClientContext(std::shared_ptr<DisplayConfig::ConfigCallback> callback,DisplayConfig::ConfigInterface ** intf)98 int HWCSession::RegisterClientContext(std::shared_ptr<DisplayConfig::ConfigCallback> callback,
99 DisplayConfig::ConfigInterface **intf) {
100 if (!intf) {
101 DLOGE("Invalid DisplayConfigIntf location");
102 return -EINVAL;
103 }
104
105 std::weak_ptr<DisplayConfig::ConfigCallback> wp_callback = callback;
106 DisplayConfigImpl *impl = new DisplayConfigImpl(wp_callback, this);
107 *intf = impl;
108
109 return 0;
110 }
111
UnRegisterClientContext(DisplayConfig::ConfigInterface * intf)112 void HWCSession::UnRegisterClientContext(DisplayConfig::ConfigInterface *intf) {
113 delete static_cast<DisplayConfigImpl *>(intf);
114 }
115
DisplayConfigImpl(std::weak_ptr<DisplayConfig::ConfigCallback> callback,HWCSession * hwc_session)116 HWCSession::DisplayConfigImpl::DisplayConfigImpl(
117 std::weak_ptr<DisplayConfig::ConfigCallback> callback,
118 HWCSession *hwc_session) {
119 callback_ = callback;
120 hwc_session_ = hwc_session;
121 }
122
IsDisplayConnected(DispType dpy,bool * connected)123 int HWCSession::DisplayConfigImpl::IsDisplayConnected(DispType dpy, bool *connected) {
124 int disp_id = MapDisplayType(dpy);
125 int disp_idx = hwc_session_->GetDisplayIndex(disp_id);
126
127 if (disp_idx == -1) {
128 DLOGE("Invalid display = %d", disp_id);
129 return -EINVAL;
130 } else {
131 SEQUENCE_WAIT_SCOPE_LOCK(hwc_session_->locker_[disp_idx]);
132 *connected = hwc_session_->hwc_display_[disp_idx];
133 }
134
135 return 0;
136 }
137
SetDisplayStatus(int disp_id,HWCDisplay::DisplayStatus status)138 int HWCSession::SetDisplayStatus(int disp_id, HWCDisplay::DisplayStatus status) {
139 int disp_idx = GetDisplayIndex(disp_id);
140 int err = -EINVAL;
141 if (disp_idx == -1) {
142 DLOGE("Invalid display = %d", disp_id);
143 return -EINVAL;
144 }
145
146 if (disp_idx == qdutils::DISPLAY_PRIMARY) {
147 DLOGE("Not supported for this display");
148 return err;
149 }
150
151 {
152 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
153 if (!hwc_display_[disp_idx]) {
154 DLOGW("Display is not connected");
155 return err;
156 }
157 DLOGI("Display = %d, Status = %d", disp_idx, status);
158 err = hwc_display_[disp_idx]->SetDisplayStatus(status);
159 if (err != 0) {
160 return err;
161 }
162 }
163
164 if (status == HWCDisplay::kDisplayStatusResume || status == HWCDisplay::kDisplayStatusPause) {
165 hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
166 if (active_builtin_disp_id < HWCCallbacks::kNumRealDisplays) {
167 {
168 SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
169 hwc_display_[active_builtin_disp_id]->ResetValidation();
170 }
171 callbacks_.Refresh(active_builtin_disp_id);
172 }
173 }
174
175 return err;
176 }
177
SetDisplayStatus(DispType dpy,DisplayConfig::ExternalStatus status)178 int HWCSession::DisplayConfigImpl::SetDisplayStatus(DispType dpy,
179 DisplayConfig::ExternalStatus status) {
180 return hwc_session_->SetDisplayStatus(MapDisplayType(dpy), MapExternalStatus(status));
181 }
182
ConfigureDynRefreshRate(DisplayConfig::DynRefreshRateOp op,uint32_t refresh_rate)183 int HWCSession::DisplayConfigImpl::ConfigureDynRefreshRate(DisplayConfig::DynRefreshRateOp op,
184 uint32_t refresh_rate) {
185 SEQUENCE_WAIT_SCOPE_LOCK(hwc_session_->locker_[HWC_DISPLAY_PRIMARY]);
186 HWCDisplay *hwc_display = hwc_session_->hwc_display_[HWC_DISPLAY_PRIMARY];
187
188 if (!hwc_display) {
189 DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
190 return -EINVAL;
191 }
192
193 switch (op) {
194 case DisplayConfig::DynRefreshRateOp::kDisableMetadata:
195 return hwc_display->Perform(HWCDisplayBuiltIn::SET_METADATA_DYN_REFRESH_RATE, false);
196
197 case DisplayConfig::DynRefreshRateOp::kEnableMetadata:
198 return hwc_display->Perform(HWCDisplayBuiltIn::SET_METADATA_DYN_REFRESH_RATE, true);
199
200 case DisplayConfig::DynRefreshRateOp::kSetBinder:
201 return hwc_display->Perform(HWCDisplayBuiltIn::SET_BINDER_DYN_REFRESH_RATE, refresh_rate);
202
203 default:
204 DLOGW("Invalid operation %d", op);
205 return -EINVAL;
206 }
207
208 return 0;
209 }
210
GetConfigCount(int disp_id,uint32_t * count)211 int HWCSession::GetConfigCount(int disp_id, uint32_t *count) {
212 int disp_idx = GetDisplayIndex(disp_id);
213 if (disp_idx == -1) {
214 DLOGE("Invalid display = %d", disp_id);
215 return -EINVAL;
216 }
217
218 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
219
220 if (hwc_display_[disp_idx]) {
221 return hwc_display_[disp_idx]->GetDisplayConfigCount(count);
222 }
223
224 return -EINVAL;
225 }
226
GetConfigCount(DispType dpy,uint32_t * count)227 int HWCSession::DisplayConfigImpl::GetConfigCount(DispType dpy, uint32_t *count) {
228 return hwc_session_->GetConfigCount(MapDisplayType(dpy), count);
229 }
230
GetActiveConfigIndex(int disp_id,uint32_t * config)231 int HWCSession::GetActiveConfigIndex(int disp_id, uint32_t *config) {
232 int disp_idx = GetDisplayIndex(disp_id);
233 if (disp_idx == -1) {
234 DLOGE("Invalid display = %d", disp_id);
235 return -EINVAL;
236 }
237
238 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
239
240 if (hwc_display_[disp_idx]) {
241 return hwc_display_[disp_idx]->GetActiveDisplayConfig(config);
242 }
243
244 return -EINVAL;
245 }
246
GetActiveConfig(DispType dpy,uint32_t * config)247 int HWCSession::DisplayConfigImpl::GetActiveConfig(DispType dpy, uint32_t *config) {
248 return hwc_session_->GetActiveConfigIndex(MapDisplayType(dpy), config);
249 }
250
SetActiveConfigIndex(int disp_id,uint32_t config)251 int HWCSession::SetActiveConfigIndex(int disp_id, uint32_t config) {
252 int disp_idx = GetDisplayIndex(disp_id);
253 if (disp_idx == -1) {
254 DLOGE("Invalid display = %d", disp_id);
255 return -EINVAL;
256 }
257
258 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
259 int error = -EINVAL;
260 if (hwc_display_[disp_idx]) {
261 error = hwc_display_[disp_idx]->SetActiveDisplayConfig(config);
262 if (!error) {
263 callbacks_.Refresh(0);
264 }
265 }
266
267 return error;
268 }
269
SetActiveConfig(DispType dpy,uint32_t config)270 int HWCSession::DisplayConfigImpl::SetActiveConfig(DispType dpy, uint32_t config) {
271 return hwc_session_->SetActiveConfigIndex(MapDisplayType(dpy), config);
272 }
273
GetDisplayAttributes(uint32_t config_index,DispType dpy,DisplayConfig::Attributes * attributes)274 int HWCSession::DisplayConfigImpl::GetDisplayAttributes(uint32_t config_index, DispType dpy,
275 DisplayConfig::Attributes *attributes) {
276 int error = -EINVAL;
277 int disp_id = MapDisplayType(dpy);
278 int disp_idx = hwc_session_->GetDisplayIndex(disp_id);
279
280 if (disp_idx == -1) {
281 DLOGE("Invalid display = %d", disp_id);
282 } else {
283 SEQUENCE_WAIT_SCOPE_LOCK(hwc_session_->locker_[disp_idx]);
284 if (hwc_session_->hwc_display_[disp_idx]) {
285 DisplayConfigVariableInfo var_info;
286 error = hwc_session_->hwc_display_[disp_idx]->GetDisplayAttributesForConfig(INT(config_index),
287 &var_info);
288 if (!error) {
289 attributes->vsync_period = var_info.vsync_period_ns;
290 attributes->x_res = var_info.x_pixels;
291 attributes->y_res = var_info.y_pixels;
292 attributes->x_dpi = var_info.x_dpi;
293 attributes->y_dpi = var_info.y_dpi;
294 attributes->panel_type = DisplayConfig::DisplayPortType::kDefault;
295 attributes->is_yuv = var_info.is_yuv;
296 }
297 }
298 }
299
300 return error;
301 }
302
SetPanelBrightness(uint32_t level)303 int HWCSession::DisplayConfigImpl::SetPanelBrightness(uint32_t level) {
304 if (!(0 <= level && level <= 255)) {
305 return -EINVAL;
306 }
307
308 if (level == 0) {
309 return INT32(hwc_session_->SetDisplayBrightness(HWC_DISPLAY_PRIMARY, -1.0f));
310 } else {
311 return INT32(hwc_session_->SetDisplayBrightness(HWC_DISPLAY_PRIMARY, (level - 1)/254.0f));
312 }
313 }
314
GetPanelBrightness(uint32_t * level)315 int HWCSession::DisplayConfigImpl::GetPanelBrightness(uint32_t *level) {
316 float brightness = -1.0f;
317 int error = -EINVAL;
318
319 error = hwc_session_->getDisplayBrightness(HWC_DISPLAY_PRIMARY, &brightness);
320 if (brightness == -1.0f) {
321 *level = 0;
322 } else {
323 *level = static_cast<uint32_t>(254.0f*brightness + 1);
324 }
325
326 return error;
327 }
328
MinHdcpEncryptionLevelChanged(int disp_id,uint32_t min_enc_level)329 int HWCSession::MinHdcpEncryptionLevelChanged(int disp_id, uint32_t min_enc_level) {
330 DLOGI("Display %d", disp_id);
331
332 // SSG team hardcoded disp_id as external because it applies to external only but SSG team sends
333 // this level irrespective of external connected or not. So to honor the call, make disp_id to
334 // primary & set level.
335 disp_id = HWC_DISPLAY_PRIMARY;
336 int disp_idx = GetDisplayIndex(disp_id);
337 if (disp_idx == -1) {
338 DLOGE("Invalid display = %d", disp_id);
339 return -EINVAL;
340 }
341
342 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
343 HWCDisplay *hwc_display = hwc_display_[disp_idx];
344 if (!hwc_display) {
345 DLOGE("Display = %d is not connected.", disp_idx);
346 return -EINVAL;
347 }
348
349 return hwc_display->OnMinHdcpEncryptionLevelChange(min_enc_level);
350 }
351
MinHdcpEncryptionLevelChanged(DispType dpy,uint32_t min_enc_level)352 int HWCSession::DisplayConfigImpl::MinHdcpEncryptionLevelChanged(DispType dpy,
353 uint32_t min_enc_level) {
354 return hwc_session_->MinHdcpEncryptionLevelChanged(MapDisplayType(dpy), min_enc_level);
355 }
356
RefreshScreen()357 int HWCSession::DisplayConfigImpl::RefreshScreen() {
358 SEQUENCE_WAIT_SCOPE_LOCK(hwc_session_->locker_[HWC_DISPLAY_PRIMARY]);
359 hwc_session_->callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
360 return 0;
361 }
362
ControlPartialUpdate(int disp_id,bool enable)363 int HWCSession::ControlPartialUpdate(int disp_id, bool enable) {
364 int disp_idx = GetDisplayIndex(disp_id);
365 if (disp_idx == -1) {
366 DLOGE("Invalid display = %d", disp_id);
367 return -EINVAL;
368 }
369
370 if (disp_idx != HWC_DISPLAY_PRIMARY) {
371 DLOGW("CONTROL_PARTIAL_UPDATE is not applicable for display = %d", disp_idx);
372 return -EINVAL;
373 }
374
375 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
376 HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
377 if (!hwc_display) {
378 DLOGE("primary display object is not instantiated");
379 return -EINVAL;
380 }
381
382 uint32_t pending = 0;
383 DisplayError hwc_error = hwc_display->ControlPartialUpdate(enable, &pending);
384
385 if (hwc_error == kErrorNone) {
386 if (!pending) {
387 return 0;
388 }
389 } else if (hwc_error == kErrorNotSupported) {
390 return 0;
391 } else {
392 return -EINVAL;
393 }
394
395 // Todo(user): Unlock it before sending events to client. It may cause deadlocks in future.
396 callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
397
398 // Wait until partial update control is complete
399 int error = locker_[disp_idx].WaitFinite(kCommitDoneTimeoutMs);
400
401 return error;
402 }
403
ControlPartialUpdate(DispType dpy,bool enable)404 int HWCSession::DisplayConfigImpl::ControlPartialUpdate(DispType dpy, bool enable) {
405 return hwc_session_->ControlPartialUpdate(MapDisplayType(dpy), enable);
406 }
407
ToggleScreenUpdate(bool on)408 int HWCSession::ToggleScreenUpdate(bool on) {
409 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
410
411 int error = -EINVAL;
412 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
413 error = hwc_display_[HWC_DISPLAY_PRIMARY]->ToggleScreenUpdates(on);
414 if (error) {
415 DLOGE("Failed to toggle screen updates = %d. Error = %d", on, error);
416 }
417 }
418
419 return error;
420 }
421
ToggleScreenUpdate(bool on)422 int HWCSession::DisplayConfigImpl::ToggleScreenUpdate(bool on) {
423 return hwc_session_->ToggleScreenUpdate(on);
424 }
425
SetIdleTimeout(uint32_t value)426 int HWCSession::SetIdleTimeout(uint32_t value) {
427 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
428
429 int inactive_ms = IDLE_TIMEOUT_INACTIVE_MS;
430 Debug::Get()->GetProperty(IDLE_TIME_INACTIVE_PROP, &inactive_ms);
431 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
432 hwc_display_[HWC_DISPLAY_PRIMARY]->SetIdleTimeoutMs(value, inactive_ms);
433 return 0;
434 }
435
436 DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
437 return -ENODEV;
438 }
439
SetIdleTimeout(uint32_t value)440 int HWCSession::DisplayConfigImpl::SetIdleTimeout(uint32_t value) {
441 return hwc_session_->SetIdleTimeout(value);
442 }
443
GetHDRCapabilities(DispType dpy,DisplayConfig::HDRCapsParams * caps)444 int HWCSession::DisplayConfigImpl::GetHDRCapabilities(DispType dpy,
445 DisplayConfig::HDRCapsParams *caps) {
446 int error = -EINVAL;
447
448 do {
449 int disp_id = MapDisplayType(dpy);
450 int disp_idx = hwc_session_->GetDisplayIndex(disp_id);
451 if (disp_idx == -1) {
452 DLOGE("Invalid display = %d", disp_id);
453 break;
454 }
455
456 SCOPE_LOCK(hwc_session_->locker_[disp_id]);
457 HWCDisplay *hwc_display = hwc_session_->hwc_display_[disp_idx];
458 if (!hwc_display) {
459 DLOGW("Display = %d is not connected.", disp_idx);
460 error = -ENODEV;
461 break;
462 }
463
464 // query number of hdr types
465 uint32_t out_num_types = 0;
466 float out_max_luminance = 0.0f;
467 float out_max_average_luminance = 0.0f;
468 float out_min_luminance = 0.0f;
469 if (hwc_display->GetHdrCapabilities(&out_num_types, nullptr, &out_max_luminance,
470 &out_max_average_luminance, &out_min_luminance)
471 != HWC2::Error::None) {
472 break;
473 }
474 if (!out_num_types) {
475 error = 0;
476 break;
477 }
478
479 // query hdr caps
480 caps->supported_hdr_types.resize(out_num_types);
481
482 if (hwc_display->GetHdrCapabilities(&out_num_types, caps->supported_hdr_types.data(),
483 &out_max_luminance, &out_max_average_luminance,
484 &out_min_luminance) == HWC2::Error::None) {
485 error = 0;
486 }
487 } while (false);
488
489 return error;
490 }
491
SetCameraLaunchStatus(uint32_t on)492 int HWCSession::SetCameraLaunchStatus(uint32_t on) {
493 if (null_display_mode_) {
494 return 0;
495 }
496
497 if (!core_intf_) {
498 DLOGW("core_intf_ not initialized.");
499 return -ENOENT;
500 }
501
502 HWBwModes mode = on > 0 ? kBwVFEOn : kBwVFEOff;
503
504 if (core_intf_->SetMaxBandwidthMode(mode) != kErrorNone) {
505 return -EINVAL;
506 }
507
508 // trigger invalidate to apply new bw caps.
509 callbacks_.Refresh(0);
510
511 return 0;
512 }
513
SetCameraLaunchStatus(uint32_t on)514 int HWCSession::DisplayConfigImpl::SetCameraLaunchStatus(uint32_t on) {
515 return hwc_session_->SetCameraLaunchStatus(on);
516 }
517
518 #ifdef DISPLAY_CONFIG_CAMERA_SMOOTH_APIs_1_0
SetCameraSmoothInfo(CameraSmoothOp op,uint32_t fps)519 int HWCSession::DisplayConfigImpl::SetCameraSmoothInfo(CameraSmoothOp op, uint32_t fps) {
520 std::shared_ptr<DisplayConfig::ConfigCallback> callback = hwc_session_->camera_callback_.lock();
521 if (!callback) {
522 return -EAGAIN;
523 }
524
525 callback->NotifyCameraSmoothInfo(op, fps);
526
527 return 0;
528 }
529
ControlCameraSmoothCallback(bool enable)530 int HWCSession::DisplayConfigImpl::ControlCameraSmoothCallback(bool enable) {
531 if (enable) {
532 hwc_session_->camera_callback_ = callback_;
533 } else {
534 hwc_session_->camera_callback_.reset();
535 }
536
537 return 0;
538 }
539 #endif
540
DisplayBWTransactionPending(bool * status)541 int HWCSession::DisplayBWTransactionPending(bool *status) {
542 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
543
544 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
545 if (sync_wait(bw_mode_release_fd_, 0) < 0) {
546 DLOGI("bw_transaction_release_fd is not yet signaled: err= %s", strerror(errno));
547 *status = false;
548 }
549
550 return 0;
551 }
552
553 DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
554 return -ENODEV;
555 }
556
DisplayBWTransactionPending(bool * status)557 int HWCSession::DisplayConfigImpl::DisplayBWTransactionPending(bool *status) {
558 return hwc_session_->DisplayBWTransactionPending(status);
559 }
560
ControlIdlePowerCollapse(bool enable,bool synchronous)561 int HWCSession::ControlIdlePowerCollapse(bool enable, bool synchronous) {
562 hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
563 if (active_builtin_disp_id >= HWCCallbacks::kNumDisplays) {
564 DLOGE("No active displays");
565 return -EINVAL;
566 }
567 SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
568
569 if (hwc_display_[active_builtin_disp_id]) {
570 if (!enable) {
571 if (!idle_pc_ref_cnt_) {
572 auto err = hwc_display_[active_builtin_disp_id]->ControlIdlePowerCollapse(enable,
573 synchronous);
574 if (err != kErrorNone) {
575 return (err == kErrorNotSupported) ? 0 : -EINVAL;
576 }
577 callbacks_.Refresh(active_builtin_disp_id);
578 int error = locker_[active_builtin_disp_id].WaitFinite(kCommitDoneTimeoutMs);
579 if (error == ETIMEDOUT) {
580 DLOGE("Timed out!! Next frame commit done event not received!!");
581 return error;
582 }
583 DLOGI("Idle PC disabled!!");
584 }
585 idle_pc_ref_cnt_++;
586 } else if (idle_pc_ref_cnt_ > 0) {
587 if (!(idle_pc_ref_cnt_ - 1)) {
588 auto err = hwc_display_[active_builtin_disp_id]->ControlIdlePowerCollapse(enable,
589 synchronous);
590 if (err != kErrorNone) {
591 return (err == kErrorNotSupported) ? 0 : -EINVAL;
592 }
593 DLOGI("Idle PC enabled!!");
594 }
595 idle_pc_ref_cnt_--;
596 }
597 return 0;
598 }
599
600 DLOGW("Display = %d is not connected.", UINT32(active_builtin_disp_id));
601 return -ENODEV;
602 }
603
ControlIdlePowerCollapse(bool enable,bool synchronous)604 int HWCSession::DisplayConfigImpl::ControlIdlePowerCollapse(bool enable, bool synchronous) {
605 return hwc_session_->ControlIdlePowerCollapse(enable, synchronous);
606 }
607
IsWbUbwcSupported(bool * value)608 int HWCSession::IsWbUbwcSupported(bool *value) {
609 HWDisplaysInfo hw_displays_info = {};
610 DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
611 if (error != kErrorNone) {
612 return -EINVAL;
613 }
614
615 for (auto &iter : hw_displays_info) {
616 auto &info = iter.second;
617 if (info.display_type == kVirtual && info.is_wb_ubwc_supported) {
618 *value = 1;
619 }
620 }
621
622 return error;
623 }
624
getDisplayBrightness(uint32_t display,float * brightness)625 int32_t HWCSession::getDisplayBrightness(uint32_t display, float *brightness) {
626 if (!brightness) {
627 return HWC2_ERROR_BAD_PARAMETER;
628 }
629
630 if (display >= HWCCallbacks::kNumDisplays) {
631 return HWC2_ERROR_BAD_DISPLAY;
632 }
633
634 SEQUENCE_WAIT_SCOPE_LOCK(locker_[display]);
635 int32_t error = -EINVAL;
636 *brightness = -1.0f;
637
638 HWCDisplay *hwc_display = hwc_display_[display];
639 if (hwc_display && hwc_display_[display]->GetDisplayClass() == DISPLAY_CLASS_BUILTIN) {
640 error = INT32(hwc_display_[display]->GetPanelBrightness(brightness));
641 if (error) {
642 DLOGE("Failed to get the panel brightness. Error = %d", error);
643 }
644 }
645
646 return error;
647 }
648
getDisplayMaxBrightness(uint32_t display,uint32_t * max_brightness_level)649 int32_t HWCSession::getDisplayMaxBrightness(uint32_t display, uint32_t *max_brightness_level) {
650 if (!max_brightness_level) {
651 return HWC2_ERROR_BAD_PARAMETER;
652 }
653
654 if (display >= HWCCallbacks::kNumDisplays) {
655 return HWC2_ERROR_BAD_DISPLAY;
656 }
657
658 int32_t error = -EINVAL;
659 HWCDisplay *hwc_display = hwc_display_[display];
660 if (hwc_display && hwc_display_[display]->GetDisplayClass() == DISPLAY_CLASS_BUILTIN) {
661 error = INT32(hwc_display_[display]->GetPanelMaxBrightness(max_brightness_level));
662 if (error) {
663 DLOGE("Failed to get the panel max brightness, display %u error %d", display, error);
664 }
665 }
666
667 return error;
668 }
669
SetDisplayAnimating(uint64_t display_id,bool animating)670 int HWCSession::DisplayConfigImpl::SetDisplayAnimating(uint64_t display_id, bool animating) {
671 return hwc_session_->CallDisplayFunction(display_id, &HWCDisplay::SetDisplayAnimating, animating);
672 }
673
GetWriteBackCapabilities(bool * isWbUbwcSupported)674 int HWCSession::DisplayConfigImpl::GetWriteBackCapabilities(bool *isWbUbwcSupported) {
675 return hwc_session_->IsWbUbwcSupported(isWbUbwcSupported);
676 }
677
SetDisplayDppsAdROI(uint32_t display_id,uint32_t h_start,uint32_t h_end,uint32_t v_start,uint32_t v_end,uint32_t factor_in,uint32_t factor_out)678 int HWCSession::SetDisplayDppsAdROI(uint32_t display_id, uint32_t h_start,
679 uint32_t h_end, uint32_t v_start, uint32_t v_end,
680 uint32_t factor_in, uint32_t factor_out) {
681 return CallDisplayFunction(display_id,
682 &HWCDisplay::SetDisplayDppsAdROI, h_start, h_end, v_start, v_end,
683 factor_in, factor_out);
684 }
685
SetDisplayDppsAdROI(uint32_t display_id,uint32_t h_start,uint32_t h_end,uint32_t v_start,uint32_t v_end,uint32_t factor_in,uint32_t factor_out)686 int HWCSession::DisplayConfigImpl::SetDisplayDppsAdROI(uint32_t display_id, uint32_t h_start,
687 uint32_t h_end, uint32_t v_start,
688 uint32_t v_end, uint32_t factor_in,
689 uint32_t factor_out) {
690 return hwc_session_->SetDisplayDppsAdROI(display_id, h_start, h_end, v_start, v_end,
691 factor_in, factor_out);
692 }
693
UpdateVSyncSourceOnPowerModeOff()694 int HWCSession::DisplayConfigImpl::UpdateVSyncSourceOnPowerModeOff() {
695 hwc_session_->update_vsync_on_power_off_ = true;
696 return 0;
697 }
698
UpdateVSyncSourceOnPowerModeDoze()699 int HWCSession::DisplayConfigImpl::UpdateVSyncSourceOnPowerModeDoze() {
700 hwc_session_->update_vsync_on_doze_ = true;
701 return 0;
702 }
703
IsPowerModeOverrideSupported(uint32_t disp_id,bool * supported)704 int HWCSession::DisplayConfigImpl::IsPowerModeOverrideSupported(uint32_t disp_id,
705 bool *supported) {
706 if (!hwc_session_->async_powermode_ || (disp_id > HWCCallbacks::kNumRealDisplays)) {
707 *supported = false;
708 } else {
709 *supported = true;
710 }
711
712 return 0;
713 }
714
SetPowerMode(uint32_t disp_id,DisplayConfig::PowerMode power_mode)715 int HWCSession::DisplayConfigImpl::SetPowerMode(uint32_t disp_id,
716 DisplayConfig::PowerMode power_mode) {
717 SCOPE_LOCK(hwc_session_->display_config_locker_);
718
719 bool supported = false;
720 IsPowerModeOverrideSupported(disp_id, &supported);
721 if (!supported) {
722 return 0;
723 }
724 // Added this flag for pixel
725 hwc_session_->async_power_mode_triggered_ = true;
726 // Active builtin display needs revalidation
727 hwc2_display_t active_builtin_disp_id = hwc_session_->GetActiveBuiltinDisplay();
728 HWC2::PowerMode previous_mode = hwc_session_->hwc_display_[disp_id]->GetCurrentPowerMode();
729
730 DLOGI("disp_id: %d power_mode: %d", disp_id, power_mode);
731 auto mode = static_cast<HWC2::PowerMode>(power_mode);
732
733 HWCDisplay::HWCLayerStack stack = {};
734 hwc2_display_t dummy_disp_id = hwc_session_->map_hwc_display_.at(disp_id);
735
736 // Power state transition start.
737 // Acquire the display's power-state transition var read lock.
738 hwc_session_->power_state_[disp_id].Lock();
739 hwc_session_->power_state_transition_[disp_id] = true;
740 hwc_session_->locker_[disp_id].Lock(); // Lock the real display.
741 hwc_session_->locker_[dummy_disp_id].Lock(); // Lock the corresponding dummy display.
742
743 // Place the real display's layer-stack on the dummy display.
744 hwc_session_->hwc_display_[disp_id]->GetLayerStack(&stack);
745 hwc_session_->hwc_display_[dummy_disp_id]->SetLayerStack(&stack);
746 hwc_session_->hwc_display_[dummy_disp_id]->UpdatePowerMode(
747 hwc_session_->hwc_display_[disp_id]->GetCurrentPowerMode());
748
749 buffer_handle_t target = 0;
750 shared_ptr<Fence> acquire_fence = nullptr;
751 int32_t dataspace = 0;
752 hwc_region_t damage = {};
753 VsyncPeriodNanos vsync_period = 16600000;
754 hwc_session_->hwc_display_[disp_id]->GetClientTarget(
755 target, acquire_fence, dataspace, damage);
756 hwc_session_->hwc_display_[dummy_disp_id]->SetClientTarget(
757 target, acquire_fence, dataspace, damage);
758
759
760
761 hwc_session_->hwc_display_[disp_id]->GetDisplayVsyncPeriod(&vsync_period);
762 hwc_session_->hwc_display_[dummy_disp_id]->SetDisplayVsyncPeriod(vsync_period);
763
764 hwc_session_->locker_[dummy_disp_id].Unlock(); // Release the dummy display.
765 // Release the display's power-state transition var read lock.
766 hwc_session_->power_state_[disp_id].Unlock();
767
768 // From now, till power-state transition ends, for operations that need to be non-blocking, do
769 // those operations on the dummy display.
770
771 // Perform the actual [synchronous] power-state change.
772 hwc_session_->hwc_display_[disp_id]->SetPowerMode(mode, false /* teardown */);
773
774 // Power state transition end.
775 // Acquire the display's power-state transition var read lock.
776 hwc_session_->power_state_[disp_id].Lock();
777 hwc_session_->power_state_transition_[disp_id] = false;
778 hwc_session_->locker_[dummy_disp_id].Lock(); // Lock the dummy display.
779
780 // Retrieve the real display's layer-stack from the dummy display.
781 hwc_session_->hwc_display_[dummy_disp_id]->GetLayerStack(&stack);
782 hwc_session_->hwc_display_[disp_id]->SetLayerStack(&stack);
783 bool vsync_pending = hwc_session_->hwc_display_[dummy_disp_id]->VsyncEnablePending();
784 if (vsync_pending) {
785 hwc_session_->hwc_display_[disp_id]->SetVsyncEnabled(HWC2::Vsync::Enable);
786 }
787 hwc_session_->hwc_display_[dummy_disp_id]->GetClientTarget(
788 target, acquire_fence, dataspace, damage);
789 hwc_session_->hwc_display_[disp_id]->SetClientTarget(
790 target, acquire_fence, dataspace, damage);
791
792 // Read display has got layerstack. Update the fences.
793 hwc_session_->hwc_display_[disp_id]->PostPowerMode();
794
795 hwc_session_->locker_[dummy_disp_id].Unlock(); // Release the dummy display.
796 hwc_session_->locker_[disp_id].Unlock(); // Release the real display.
797 // Release the display's power-state transition var read lock.
798 hwc_session_->power_state_[disp_id].Unlock();
799
800 HWC2::PowerMode new_mode = hwc_session_->hwc_display_[disp_id]->GetCurrentPowerMode();
801 if (active_builtin_disp_id < HWCCallbacks::kNumRealDisplays &&
802 hwc_session_->hwc_display_[disp_id]->IsFirstCommitDone() &&
803 WaitForResourceNeeded(previous_mode, new_mode)) {
804 hwc_session_->WaitForResources(true, active_builtin_disp_id, disp_id);
805 }
806
807 return 0;
808 }
809
IsHDRSupported(uint32_t disp_id,bool * supported)810 int HWCSession::DisplayConfigImpl::IsHDRSupported(uint32_t disp_id, bool *supported) {
811 if (disp_id < 0 || disp_id >= HWCCallbacks::kNumDisplays) {
812 DLOGE("Not valid display");
813 return -EINVAL;
814 }
815 SCOPE_LOCK(hwc_session_->hdr_locker_[disp_id]);
816
817 if (hwc_session_->is_hdr_display_.size() <= disp_id) {
818 DLOGW("is_hdr_display_ is not initialized for display %d!! Reporting it as HDR not supported",
819 disp_id);
820 *supported = false;
821 return 0;
822 }
823
824 *supported = static_cast<bool>(hwc_session_->is_hdr_display_[disp_id]);
825 return 0;
826 }
827
IsWCGSupported(uint32_t disp_id,bool * supported)828 int HWCSession::DisplayConfigImpl::IsWCGSupported(uint32_t disp_id, bool *supported) {
829 // todo(user): Query wcg from sdm. For now assume them same.
830 return IsHDRSupported(disp_id, supported);
831 }
832
SetLayerAsMask(uint32_t disp_id,uint64_t layer_id)833 int HWCSession::DisplayConfigImpl::SetLayerAsMask(uint32_t disp_id, uint64_t layer_id) {
834 if (disp_id < 0 || disp_id >= HWCCallbacks::kNumDisplays) {
835 DLOGE("Not valid display");
836 return -EINVAL;
837 }
838 SCOPE_LOCK(hwc_session_->locker_[disp_id]);
839 HWCDisplay *hwc_display = hwc_session_->hwc_display_[disp_id];
840 if (!hwc_display) {
841 DLOGW("Display = %d is not connected.", disp_id);
842 return -EINVAL;
843 }
844
845 if (hwc_session_->disable_mask_layer_hint_) {
846 DLOGW("Mask layer hint is disabled!");
847 return -EINVAL;
848 }
849
850 auto hwc_layer = hwc_display->GetHWCLayer(layer_id);
851 if (hwc_layer == nullptr) {
852 return -EINVAL;
853 }
854
855 hwc_layer->SetLayerAsMask();
856
857 return 0;
858 }
859
GetDebugProperty(const std::string prop_name,std::string * value)860 int HWCSession::DisplayConfigImpl::GetDebugProperty(const std::string prop_name,
861 std::string *value) {
862 std::string vendor_prop_name = DISP_PROP_PREFIX;
863 int error = -EINVAL;
864 char val[64] = {};
865
866 vendor_prop_name += prop_name.c_str();
867 if (HWCDebugHandler::Get()->GetProperty(vendor_prop_name.c_str(), val) == kErrorNone) {
868 *value = val;
869 error = 0;
870 }
871
872 return error;
873 }
874
GetActiveBuiltinDisplayAttributes(DisplayConfig::Attributes * attr)875 int HWCSession::DisplayConfigImpl::GetActiveBuiltinDisplayAttributes(
876 DisplayConfig::Attributes *attr) {
877 int error = -EINVAL;
878 hwc2_display_t disp_id = hwc_session_->GetActiveBuiltinDisplay();
879
880 if (disp_id >= HWCCallbacks::kNumDisplays) {
881 DLOGE("Invalid display = %d", UINT32(disp_id));
882 } else {
883 if (hwc_session_->hwc_display_[disp_id]) {
884 uint32_t config_index = 0;
885 HWC2::Error ret = hwc_session_->hwc_display_[disp_id]->GetActiveConfig(&config_index);
886 if (ret != HWC2::Error::None) {
887 goto err;
888 }
889 DisplayConfigVariableInfo var_info;
890 error = hwc_session_->hwc_display_[disp_id]->GetDisplayAttributesForConfig(INT(config_index),
891 &var_info);
892 if (!error) {
893 attr->vsync_period = var_info.vsync_period_ns;
894 attr->x_res = var_info.x_pixels;
895 attr->y_res = var_info.y_pixels;
896 attr->x_dpi = var_info.x_dpi;
897 attr->y_dpi = var_info.y_dpi;
898 attr->panel_type = DisplayConfig::DisplayPortType::kDefault;
899 attr->is_yuv = var_info.is_yuv;
900 }
901 }
902 }
903
904 err:
905 return error;
906 }
907
SetPanelLuminanceAttributes(uint32_t disp_id,float pan_min_lum,float pan_max_lum)908 int HWCSession::DisplayConfigImpl::SetPanelLuminanceAttributes(uint32_t disp_id, float pan_min_lum,
909 float pan_max_lum) {
910 // currently doing only for virtual display
911 if (disp_id != qdutils::DISPLAY_VIRTUAL) {
912 return -EINVAL;
913 }
914
915 // check for out of range luminance values
916 if (pan_min_lum <= 0.0f || pan_min_lum >= 1.0f ||
917 pan_max_lum <= 100.0f || pan_max_lum >= 1000.0f) {
918 return -EINVAL;
919 }
920
921 std::lock_guard<std::mutex> obj(hwc_session_->mutex_lum_);
922 hwc_session_->set_min_lum_ = pan_min_lum;
923 hwc_session_->set_max_lum_ = pan_max_lum;
924 DLOGI("set max_lum %f, min_lum %f", pan_max_lum, pan_min_lum);
925
926 return 0;
927 }
928
IsBuiltInDisplay(uint32_t disp_id,bool * is_builtin)929 int HWCSession::DisplayConfigImpl::IsBuiltInDisplay(uint32_t disp_id, bool *is_builtin) {
930 if ((hwc_session_->map_info_primary_.client_id == disp_id) &&
931 (hwc_session_->map_info_primary_.disp_type == kBuiltIn)) {
932 *is_builtin = true;
933 return 0;
934 }
935
936 for (auto &info : hwc_session_->map_info_builtin_) {
937 if (disp_id == info.client_id) {
938 *is_builtin = true;
939 return 0;
940 }
941 }
942
943 *is_builtin = false;
944 return 0;
945 }
946
GetSupportedDSIBitClks(uint32_t disp_id,std::vector<uint64_t> * bit_clks)947 int HWCSession::DisplayConfigImpl::GetSupportedDSIBitClks(uint32_t disp_id,
948 std::vector<uint64_t> *bit_clks) {
949 if (disp_id < 0 || disp_id >= HWCCallbacks::kNumDisplays) {
950 DLOGE("Not valid display");
951 return -EINVAL;
952 }
953 SCOPE_LOCK(hwc_session_->locker_[disp_id]);
954 if (!hwc_session_->hwc_display_[disp_id]) {
955 return -EINVAL;
956 }
957
958 hwc_session_->hwc_display_[disp_id]->GetSupportedDSIClock(bit_clks);
959 return 0;
960 }
961
GetDSIClk(uint32_t disp_id,uint64_t * bit_clk)962 int HWCSession::DisplayConfigImpl::GetDSIClk(uint32_t disp_id, uint64_t *bit_clk) {
963 if (disp_id < 0 || disp_id >= HWCCallbacks::kNumDisplays) {
964 DLOGE("Not valid display");
965 return -EINVAL;
966 }
967 SCOPE_LOCK(hwc_session_->locker_[disp_id]);
968 if (!hwc_session_->hwc_display_[disp_id]) {
969 return -EINVAL;
970 }
971
972 hwc_session_->hwc_display_[disp_id]->GetDynamicDSIClock(bit_clk);
973
974 return 0;
975 }
976
SetDSIClk(uint32_t disp_id,uint64_t bit_clk)977 int HWCSession::DisplayConfigImpl::SetDSIClk(uint32_t disp_id, uint64_t bit_clk) {
978 if (disp_id < 0 || disp_id >= HWCCallbacks::kNumDisplays) {
979 DLOGE("Not valid display");
980 return -EINVAL;
981 }
982 SCOPE_LOCK(hwc_session_->locker_[disp_id]);
983 if (!hwc_session_->hwc_display_[disp_id]) {
984 return -1;
985 }
986
987 return hwc_session_->hwc_display_[disp_id]->SetDynamicDSIClock(bit_clk);
988 }
989
SetCWBOutputBuffer(uint32_t disp_id,const DisplayConfig::Rect rect,bool post_processed,const native_handle_t * buffer)990 int HWCSession::DisplayConfigImpl::SetCWBOutputBuffer(uint32_t disp_id,
991 const DisplayConfig::Rect rect,
992 bool post_processed,
993 const native_handle_t *buffer) {
994 if (!callback_.lock() || !buffer) {
995 DLOGE("Invalid parameters");
996 return -1;
997 }
998
999 if (disp_id != UINT32(DisplayConfig::DisplayType::kPrimary)) {
1000 DLOGE("Only supported for primary display at present.");
1001 return -1;
1002 }
1003
1004 if (rect.left || rect.top || rect.right || rect.bottom) {
1005 DLOGE("Cropping rectangle is not supported.");
1006 return -1;
1007 }
1008
1009 // Output buffer dump is not supported, if External or Virtual display is present.
1010 int external_dpy_index = hwc_session_->GetDisplayIndex(qdutils::DISPLAY_EXTERNAL);
1011 int virtual_dpy_index = hwc_session_->GetDisplayIndex(qdutils::DISPLAY_VIRTUAL);
1012 int primary_dpy_index = hwc_session_->GetDisplayIndex(qdutils::DISPLAY_PRIMARY);
1013
1014 if (((external_dpy_index != -1) && hwc_session_->hwc_display_[external_dpy_index]) ||
1015 ((virtual_dpy_index != -1) && hwc_session_->hwc_display_[virtual_dpy_index])) {
1016 DLOGW("Output buffer dump is not supported with External or Virtual display!");
1017 return -1;
1018 }
1019
1020 // Mutex scope
1021 {
1022 SCOPE_LOCK(hwc_session_->locker_[HWC_DISPLAY_PRIMARY]);
1023 if (!hwc_session_->hwc_display_[primary_dpy_index]) {
1024 DLOGE("Display is not created yet.");
1025 return -1;
1026 }
1027 }
1028
1029 return hwc_session_->cwb_.PostBuffer(callback_, post_processed,
1030 native_handle_clone(buffer));
1031 }
1032
PostBuffer(std::weak_ptr<DisplayConfig::ConfigCallback> callback,bool post_processed,const native_handle_t * buffer)1033 int32_t HWCSession::CWB::PostBuffer(std::weak_ptr<DisplayConfig::ConfigCallback> callback,
1034 bool post_processed, const native_handle_t *buffer) {
1035 SCOPE_LOCK(queue_lock_);
1036
1037 // Ensure that async task runs only until all queued CWB requests have been fulfilled.
1038 // If cwb queue is empty, async task has not either started or async task has finished
1039 // processing previously queued cwb requests. Start new async task on such a case as
1040 // currently running async task will automatically desolve without processing more requests.
1041 bool post_future = !queue_.size();
1042
1043 QueueNode *node = new QueueNode(callback, post_processed, buffer);
1044 queue_.push(node);
1045
1046 if (post_future) {
1047 // No need to do future.get() here for previously running async task. Async method will
1048 // guarantee to exit after cwb for all queued requests is indeed complete i.e. the respective
1049 // fences have signaled and client is notified through registered callbacks. This will make
1050 // sure that the new async task does not concurrently work with previous task. Let async running
1051 // thread dissolve on its own.
1052 future_ = std::async(HWCSession::CWB::AsyncTask, this);
1053 }
1054
1055 return 0;
1056 }
1057
ProcessRequests()1058 void HWCSession::CWB::ProcessRequests() {
1059 HWCDisplay *hwc_display = hwc_session_->hwc_display_[HWC_DISPLAY_PRIMARY];
1060 Locker &locker = hwc_session_->locker_[HWC_DISPLAY_PRIMARY];
1061
1062 while (true) {
1063 QueueNode *node = nullptr;
1064 int status = 0;
1065
1066 // Mutex scope
1067 // Just check if there is a next cwb request queued, exit the thread if nothing is pending.
1068 // Do not keep mutex locked so that client can freely queue more jobs to the current thread.
1069 {
1070 SCOPE_LOCK(queue_lock_);
1071 if (!queue_.size()) {
1072 break;
1073 }
1074
1075 node = queue_.front();
1076 }
1077
1078 // Configure cwb parameters, trigger refresh, wait for commit, get the release fence and
1079 // wait for fence to signal.
1080
1081 // Mutex scope
1082 // Wait for previous commit to finish before configuring next buffer.
1083 {
1084 SEQUENCE_WAIT_SCOPE_LOCK(locker);
1085 if (hwc_display->SetReadbackBuffer(node->buffer, nullptr, node->post_processed,
1086 kCWBClientExternal) != HWC2::Error::None) {
1087 DLOGE("CWB buffer could not be set.");
1088 status = -1;
1089 }
1090 }
1091
1092 if (!status) {
1093 hwc_session_->callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
1094
1095 std::unique_lock<std::mutex> lock(mutex_);
1096 cv_.wait(lock);
1097
1098 shared_ptr<Fence> release_fence = nullptr;
1099 // Mutex scope
1100 {
1101 SCOPE_LOCK(locker);
1102 hwc_display->GetReadbackBufferFence(&release_fence);
1103 }
1104
1105 if (release_fence >= 0) {
1106 status = Fence::Wait(release_fence);
1107 } else {
1108 DLOGE("CWB release fence could not be retrieved.");
1109 status = -1;
1110 }
1111 }
1112
1113 // Notify client about buffer status and erase the node from pending request queue.
1114 std::shared_ptr<DisplayConfig::ConfigCallback> callback = node->callback.lock();
1115 if (callback) {
1116 callback->NotifyCWBBufferDone(status, node->buffer);
1117 }
1118
1119 native_handle_close(node->buffer);
1120 native_handle_delete(const_cast<native_handle_t *>(node->buffer));
1121 delete node;
1122
1123 // Mutex scope
1124 // Make sure to exit here, if queue becomes empty after erasing current node from queue,
1125 // so that the current async task does not operate concurrently with a new future task.
1126 {
1127 SCOPE_LOCK(queue_lock_);
1128 queue_.pop();
1129
1130 if (!queue_.size()) {
1131 break;
1132 }
1133 }
1134 }
1135 }
1136
AsyncTask(CWB * cwb)1137 void HWCSession::CWB::AsyncTask(CWB *cwb) {
1138 cwb->ProcessRequests();
1139 }
1140
PresentDisplayDone(hwc2_display_t disp_id)1141 void HWCSession::CWB::PresentDisplayDone(hwc2_display_t disp_id) {
1142 if (disp_id != HWC_DISPLAY_PRIMARY) {
1143 return;
1144 }
1145
1146 std::unique_lock<std::mutex> lock(mutex_);
1147 cv_.notify_one();
1148 }
1149
SetQsyncMode(uint32_t disp_id,DisplayConfig::QsyncMode mode)1150 int HWCSession::DisplayConfigImpl::SetQsyncMode(uint32_t disp_id, DisplayConfig::QsyncMode mode) {
1151 if (disp_id < 0 || disp_id >= HWCCallbacks::kNumDisplays) {
1152 DLOGE("Not valid display");
1153 return -EINVAL;
1154 }
1155 SEQUENCE_WAIT_SCOPE_LOCK(hwc_session_->locker_[disp_id]);
1156 if (!hwc_session_->hwc_display_[disp_id]) {
1157 return -1;
1158 }
1159
1160 QSyncMode qsync_mode = kQSyncModeNone;
1161 switch (mode) {
1162 case DisplayConfig::QsyncMode::kNone:
1163 qsync_mode = kQSyncModeNone;
1164 break;
1165 case DisplayConfig::QsyncMode::kWaitForFencesOneFrame:
1166 qsync_mode = kQsyncModeOneShot;
1167 break;
1168 case DisplayConfig::QsyncMode::kWaitForFencesEachFrame:
1169 qsync_mode = kQsyncModeOneShotContinuous;
1170 break;
1171 case DisplayConfig::QsyncMode::kWaitForCommitEachFrame:
1172 qsync_mode = kQSyncModeContinuous;
1173 break;
1174 }
1175
1176 hwc_session_->hwc_display_[disp_id]->SetQSyncMode(qsync_mode);
1177 return 0;
1178 }
1179
IsSmartPanelConfig(uint32_t disp_id,uint32_t config_id,bool * is_smart)1180 int HWCSession::DisplayConfigImpl::IsSmartPanelConfig(uint32_t disp_id, uint32_t config_id,
1181 bool *is_smart) {
1182 if (disp_id < 0 || disp_id >= HWCCallbacks::kNumDisplays) {
1183 DLOGE("Not valid display");
1184 return -EINVAL;
1185 }
1186 SCOPE_LOCK(hwc_session_->locker_[disp_id]);
1187 if (!hwc_session_->hwc_display_[disp_id]) {
1188 DLOGE("Display %d is not created yet.", disp_id);
1189 *is_smart = false;
1190 return -EINVAL;
1191 }
1192
1193 if (hwc_session_->hwc_display_[disp_id]->GetDisplayClass() != DISPLAY_CLASS_BUILTIN) {
1194 return false;
1195 }
1196
1197 *is_smart = hwc_session_->hwc_display_[disp_id]->IsSmartPanelConfig(config_id);
1198 return 0;
1199 }
1200
IsAsyncVDSCreationSupported(bool * supported)1201 int HWCSession::DisplayConfigImpl::IsAsyncVDSCreationSupported(bool *supported) {
1202 if (!hwc_session_->async_vds_creation_) {
1203 *supported = false;
1204 return 0;
1205 }
1206
1207 *supported = true;
1208 return 0;
1209 }
1210
CreateVirtualDisplay(uint32_t width,uint32_t height,int32_t format)1211 int HWCSession::DisplayConfigImpl::CreateVirtualDisplay(uint32_t width, uint32_t height,
1212 int32_t format) {
1213 if (!hwc_session_->async_vds_creation_) {
1214 return HWC2_ERROR_UNSUPPORTED;
1215 }
1216
1217 if (!width || !height) {
1218 return HWC2_ERROR_BAD_PARAMETER;
1219 }
1220
1221 hwc2_display_t active_builtin_disp_id = hwc_session_->GetActiveBuiltinDisplay();
1222 auto status = hwc_session_->CreateVirtualDisplayObj(width, height, &format,
1223 &hwc_session_->virtual_id_);
1224 if (status == HWC2::Error::None) {
1225 DLOGI("Created virtual display id:%" PRIu64 ", res: %dx%d",
1226 hwc_session_->virtual_id_, width, height);
1227 if (active_builtin_disp_id < HWCCallbacks::kNumRealDisplays) {
1228 hwc_session_->WaitForResources(true, active_builtin_disp_id, hwc_session_->virtual_id_);
1229 }
1230 } else {
1231 DLOGE("Failed to create virtual display: %s", to_string(status).c_str());
1232 }
1233
1234 return INT(status);
1235 }
1236
IsRotatorSupportedFormat(int hal_format,bool ubwc,bool * supported)1237 int HWCSession::DisplayConfigImpl::IsRotatorSupportedFormat(int hal_format, bool ubwc,
1238 bool *supported) {
1239 if (!hwc_session_->core_intf_) {
1240 DLOGW("core_intf_ not initialized.");
1241 *supported = false;
1242 return -EINVAL;
1243 }
1244 int flag = ubwc ? private_handle_t::PRIV_FLAGS_UBWC_ALIGNED : 0;
1245
1246 LayerBufferFormat sdm_format = HWCLayer::GetSDMFormat(hal_format, flag);
1247
1248 *supported = hwc_session_->core_intf_->IsRotatorSupportedFormat(sdm_format);
1249 return 0;
1250 }
1251
ControlQsyncCallback(bool enable)1252 int HWCSession::DisplayConfigImpl::ControlQsyncCallback(bool enable) {
1253 if (enable) {
1254 hwc_session_->qsync_callback_ = callback_;
1255 } else {
1256 hwc_session_->qsync_callback_.reset();
1257 }
1258
1259 return 0;
1260 }
1261
ControlIdleStatusCallback(bool enable)1262 int HWCSession::DisplayConfigImpl::ControlIdleStatusCallback(bool enable) {
1263 if (enable) {
1264 hwc_session_->idle_callback_ = callback_;
1265 } else {
1266 hwc_session_->idle_callback_.reset();
1267 }
1268
1269 return 0;
1270 }
1271
IsRCSupported(uint32_t disp_id,bool * supported)1272 int HWCSession::DisplayConfigImpl::IsRCSupported(uint32_t disp_id, bool *supported) {
1273 // Mask layers can potentially be shown on any display so report RC supported on all displays if
1274 // the property enables the feature for use.
1275 int val = false; // Default value.
1276 Debug::GetProperty(ENABLE_ROUNDED_CORNER, &val);
1277 *supported = val ? true: false;
1278
1279 return 0;
1280 }
1281
AllowIdleFallback()1282 int HWCSession::DisplayConfigImpl::AllowIdleFallback() {
1283 SEQUENCE_WAIT_SCOPE_LOCK(hwc_session_->locker_[HWC_DISPLAY_PRIMARY]);
1284
1285 uint32_t active_ms = 0;
1286 uint32_t inactive_ms = 0;
1287 Debug::GetIdleTimeoutMs(&active_ms, &inactive_ms);
1288 if (hwc_session_->hwc_display_[HWC_DISPLAY_PRIMARY]) {
1289 DLOGI("enable idle time active_ms:%d inactive_ms:%d",active_ms,inactive_ms);
1290 hwc_session_->hwc_display_[HWC_DISPLAY_PRIMARY]->SetIdleTimeoutMs(active_ms, inactive_ms);
1291 hwc_session_->is_idle_time_up_ = true;
1292 return 0;
1293 }
1294
1295 DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
1296 return -ENODEV;
1297 }
1298
1299 } // namespace sdm
1300