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