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