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