xref: /aosp_15_r20/external/drm_hwcomposer/hwc2_device/DrmHwcTwo.cpp (revision 0a9764fe0a15e71ebbeb85e87e10990c23aab47f)
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "drmhwc"
18 
19 #include "DrmHwcTwo.h"
20 
21 #include <cinttypes>
22 
23 #include "backend/Backend.h"
24 #include "utils/log.h"
25 
26 namespace android {
27 
RegisterCallback(int32_t descriptor,hwc2_callback_data_t data,hwc2_function_pointer_t function)28 HWC2::Error DrmHwcTwo::RegisterCallback(int32_t descriptor,
29                                         hwc2_callback_data_t data,
30                                         hwc2_function_pointer_t function) {
31   switch (static_cast<HWC2::Callback>(descriptor)) {
32     case HWC2::Callback::Hotplug: {
33       hotplug_callback_ = std::make_pair(HWC2_PFN_HOTPLUG(function), data);
34       if (function != nullptr) {
35         GetResMan().Init();
36       } else {
37         GetResMan().DeInit();
38         /* Headless display may still be here. Remove it! */
39         if (Displays().count(kPrimaryDisplay) != 0) {
40           Displays()[kPrimaryDisplay]->Deinit();
41           Displays().erase(kPrimaryDisplay);
42         }
43       }
44       break;
45     }
46     case HWC2::Callback::Refresh: {
47       refresh_callback_ = std::make_pair(HWC2_PFN_REFRESH(function), data);
48       break;
49     }
50     case HWC2::Callback::Vsync: {
51       vsync_callback_ = std::make_pair(HWC2_PFN_VSYNC(function), data);
52       break;
53     }
54 #if __ANDROID_API__ > 29
55     case HWC2::Callback::Vsync_2_4: {
56       vsync_2_4_callback_ = std::make_pair(HWC2_PFN_VSYNC_2_4(function), data);
57       break;
58     }
59     case HWC2::Callback::VsyncPeriodTimingChanged: {
60       period_timing_changed_callback_ = std::
61           make_pair(HWC2_PFN_VSYNC_PERIOD_TIMING_CHANGED(function), data);
62       break;
63     }
64 #endif
65     default:
66       break;
67   }
68   return HWC2::Error::None;
69 }
70 
SendHotplugEventToClient(hwc2_display_t displayid,DisplayStatus display_status)71 void DrmHwcTwo::SendHotplugEventToClient(hwc2_display_t displayid,
72                                          DisplayStatus display_status) {
73   auto hc = hotplug_callback_;
74 
75   if (hc.first != nullptr && hc.second != nullptr) {
76     /* For some reason HWC Service will call HWC2 API in hotplug callback
77      * handler. This is the reason we're using recursive mutex.
78      */
79     hc.first(hc.second, displayid,
80              display_status ? HWC2_CONNECTION_CONNECTED
81                             : HWC2_CONNECTION_DISCONNECTED);
82   }
83 }
84 
SendVsyncEventToClient(hwc2_display_t displayid,int64_t timestamp,uint32_t vsync_period) const85 void DrmHwcTwo::SendVsyncEventToClient(
86     hwc2_display_t displayid, int64_t timestamp,
87     [[maybe_unused]] uint32_t vsync_period) const {
88   /* vsync callback */
89 #if __ANDROID_API__ > 29
90   if (vsync_2_4_callback_.first != nullptr &&
91       vsync_2_4_callback_.second != nullptr) {
92     vsync_2_4_callback_.first(vsync_2_4_callback_.second, displayid, timestamp,
93                               vsync_period);
94   } else
95 #endif
96       if (vsync_callback_.first != nullptr &&
97           vsync_callback_.second != nullptr) {
98     vsync_callback_.first(vsync_callback_.second, displayid, timestamp);
99   }
100 }
101 
SendVsyncPeriodTimingChangedEventToClient(hwc2_display_t displayid,int64_t timestamp) const102 void DrmHwcTwo::SendVsyncPeriodTimingChangedEventToClient(
103     [[maybe_unused]] hwc2_display_t displayid,
104     [[maybe_unused]] int64_t timestamp) const {
105 #if __ANDROID_API__ > 29
106   hwc_vsync_period_change_timeline_t timeline = {
107       .newVsyncAppliedTimeNanos = timestamp,
108       .refreshRequired = false,
109       .refreshTimeNanos = 0,
110   };
111   if (period_timing_changed_callback_.first != nullptr &&
112       period_timing_changed_callback_.second != nullptr) {
113     period_timing_changed_callback_
114         .first(period_timing_changed_callback_.second, displayid, &timeline);
115   }
116 #endif
117 }
118 
SendRefreshEventToClient(hwc2_display_t displayid)119 void DrmHwcTwo::SendRefreshEventToClient(hwc2_display_t displayid) {
120   if (refresh_callback_.first != nullptr &&
121       refresh_callback_.second != nullptr) {
122     refresh_callback_.first(refresh_callback_.second, displayid);
123   }
124 }
125 
126 }  // namespace android
127