2 * Copyright (C) 2016 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #define LOG_TAG "hwc-drm-two"
19 #include "DrmHwcTwo.h"
21 #include "backend/Backend.h"
22 #include "utils/log.h"
26 DrmHwcTwo::DrmHwcTwo() = default;
28 HWC2::Error DrmHwcTwo::CreateDisplay(hwc2_display_t displ,
29 HWC2::DisplayType type) {
30 DrmDevice *drm = resource_manager_.GetDrmDevice(static_cast<int>(displ));
32 ALOGE("Failed to get a valid drmresource");
33 return HWC2::Error::NoResources;
35 displays_.emplace(std::piecewise_construct, std::forward_as_tuple(displ),
36 std::forward_as_tuple(&resource_manager_, drm, displ, type,
39 DrmCrtc *crtc = drm->GetCrtcForDisplay(static_cast<int>(displ));
41 ALOGE("Failed to get crtc for display %d", static_cast<int>(displ));
42 return HWC2::Error::BadDisplay;
44 auto display_planes = std::vector<DrmPlane *>();
45 for (const auto &plane : drm->planes()) {
46 if (plane->GetCrtcSupported(*crtc))
47 display_planes.push_back(plane.get());
49 displays_.at(displ).Init(&display_planes);
50 return HWC2::Error::None;
53 HWC2::Error DrmHwcTwo::Init() {
54 int rv = resource_manager_.Init();
56 ALOGE("Can't initialize the resource manager %d", rv);
57 return HWC2::Error::NoResources;
60 HWC2::Error ret = HWC2::Error::None;
61 for (int i = 0; i < resource_manager_.GetDisplayCount(); i++) {
62 ret = CreateDisplay(i, HWC2::DisplayType::Physical);
63 if (ret != HWC2::Error::None) {
64 ALOGE("Failed to create display %d with error %d", i, ret);
69 resource_manager_.GetUEventListener()->RegisterHotplugHandler(
70 [this] { HandleHotplugUEvent(); });
75 HWC2::Error DrmHwcTwo::CreateVirtualDisplay(uint32_t /*width*/,
78 hwc2_display_t * /*display*/) {
79 // TODO(nobody): Implement virtual display
80 return HWC2::Error::Unsupported;
83 HWC2::Error DrmHwcTwo::DestroyVirtualDisplay(hwc2_display_t /*display*/) {
84 // TODO(nobody): Implement virtual display
85 return HWC2::Error::Unsupported;
88 void DrmHwcTwo::Dump(uint32_t *outSize, char *outBuffer) {
89 if (outBuffer != nullptr) {
90 auto copied_bytes = mDumpString.copy(outBuffer, *outSize);
91 *outSize = static_cast<uint32_t>(copied_bytes);
95 std::stringstream output;
97 output << "-- drm_hwcomposer --\n\n";
99 for (std::pair<const hwc2_display_t, HwcDisplay> &dp : displays_)
100 output << dp.second.Dump();
102 mDumpString = output.str();
103 *outSize = static_cast<uint32_t>(mDumpString.size());
106 uint32_t DrmHwcTwo::GetMaxVirtualDisplayCount() {
107 // TODO(nobody): Implement virtual display
111 HWC2::Error DrmHwcTwo::RegisterCallback(int32_t descriptor,
112 hwc2_callback_data_t data,
113 hwc2_function_pointer_t function) {
114 std::unique_lock<std::mutex> lock(callback_lock_);
116 switch (static_cast<HWC2::Callback>(descriptor)) {
117 case HWC2::Callback::Hotplug: {
118 hotplug_callback_ = std::make_pair(HWC2_PFN_HOTPLUG(function), data);
120 const auto &drm_devices = resource_manager_.GetDrmDevices();
121 for (const auto &device : drm_devices)
122 HandleInitialHotplugState(device.get());
125 case HWC2::Callback::Refresh: {
126 refresh_callback_ = std::make_pair(HWC2_PFN_REFRESH(function), data);
129 case HWC2::Callback::Vsync: {
130 vsync_callback_ = std::make_pair(HWC2_PFN_VSYNC(function), data);
133 #if PLATFORM_SDK_VERSION > 29
134 case HWC2::Callback::Vsync_2_4: {
135 vsync_2_4_callback_ = std::make_pair(HWC2_PFN_VSYNC_2_4(function), data);
142 return HWC2::Error::None;
145 void DrmHwcTwo::HandleDisplayHotplug(hwc2_display_t displayid, int state) {
146 const std::lock_guard<std::mutex> lock(callback_lock_);
148 if (hotplug_callback_.first != nullptr &&
149 hotplug_callback_.second != nullptr) {
150 hotplug_callback_.first(hotplug_callback_.second, displayid,
151 state == DRM_MODE_CONNECTED
152 ? HWC2_CONNECTION_CONNECTED
153 : HWC2_CONNECTION_DISCONNECTED);
157 void DrmHwcTwo::HandleInitialHotplugState(DrmDevice *drmDevice) {
158 for (const auto &conn : drmDevice->connectors()) {
159 if (conn->state() != DRM_MODE_CONNECTED)
161 HandleDisplayHotplug(conn->display(), conn->state());
165 void DrmHwcTwo::HandleHotplugUEvent() {
166 for (const auto &drm : resource_manager_.GetDrmDevices()) {
167 for (const auto &conn : drm->connectors()) {
168 drmModeConnection old_state = conn->state();
169 drmModeConnection cur_state = conn->UpdateModes()
170 ? DRM_MODE_UNKNOWNCONNECTION
173 if (cur_state == old_state)
176 ALOGI("%s event for connector %u on display %d",
177 cur_state == DRM_MODE_CONNECTED ? "Plug" : "Unplug", conn->id(),
180 int display_id = conn->display();
181 if (cur_state == DRM_MODE_CONNECTED) {
182 auto &display = displays_.at(display_id);
183 display.ChosePreferredConfig();
185 auto &display = displays_.at(display_id);
186 display.ClearDisplay();
189 HandleDisplayHotplug(display_id, cur_state);
194 } // namespace android