xref: /aosp_15_r20/external/drm_hwcomposer/hwc3/DrmHwcThree.cpp (revision 0a9764fe0a15e71ebbeb85e87e10990c23aab47f)
1 /*
2  * Copyright (C) 2024 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 "DrmHwcThree.h"
20 
21 #include <cinttypes>
22 
23 #include "Utils.h"
24 #include "aidl/android/hardware/graphics/common/Dataspace.h"
25 #if __ANDROID_API__ >= 35
26 #include "aidl/android/hardware/graphics/common/DisplayHotplugEvent.h"
27 #endif
28 
29 namespace aidl::android::hardware::graphics::composer3::impl {
30 
31 using ::android::HwcDisplay;
32 
~DrmHwcThree()33 DrmHwcThree::~DrmHwcThree() {
34   /* Display deinit routine is handled by resource manager */
35   GetResMan().DeInit();
36 }
37 
Init(std::shared_ptr<IComposerCallback> callback)38 void DrmHwcThree::Init(std::shared_ptr<IComposerCallback> callback) {
39   composer_callback_ = std::move(callback);
40   GetResMan().Init();
41 }
42 
SendVsyncPeriodTimingChangedEventToClient(uint64_t display_id,int64_t timestamp) const43 void DrmHwcThree::SendVsyncPeriodTimingChangedEventToClient(
44     uint64_t display_id, int64_t timestamp) const {
45   VsyncPeriodChangeTimeline timeline;
46   timeline.newVsyncAppliedTimeNanos = timestamp;
47   timeline.refreshRequired = false;
48   timeline.refreshTimeNanos = 0;
49 
50   composer_callback_->onVsyncPeriodTimingChanged(static_cast<int64_t>(
51                                                      display_id),
52                                                  timeline);
53 }
54 
SendRefreshEventToClient(uint64_t display_id)55 void DrmHwcThree::SendRefreshEventToClient(uint64_t display_id) {
56   composer_resources_->SetDisplayMustValidateState(display_id, true);
57   composer_callback_->onRefresh(static_cast<int64_t>(display_id));
58 }
59 
SendVsyncEventToClient(uint64_t display_id,int64_t timestamp,uint32_t vsync_period) const60 void DrmHwcThree::SendVsyncEventToClient(uint64_t display_id, int64_t timestamp,
61                                          uint32_t vsync_period) const {
62   composer_callback_->onVsync(static_cast<int64_t>(display_id), timestamp,
63                               static_cast<int32_t>(vsync_period));
64 }
65 
66 #if __ANDROID_API__ >= 35
67 
SendHotplugEventToClient(hwc2_display_t display_id,DrmHwc::DisplayStatus display_status)68 void DrmHwcThree::SendHotplugEventToClient(
69     hwc2_display_t display_id, DrmHwc::DisplayStatus display_status) {
70   common::DisplayHotplugEvent event = common::DisplayHotplugEvent::DISCONNECTED;
71   switch (display_status) {
72     case DrmHwc::kDisconnected:
73       event = common::DisplayHotplugEvent::DISCONNECTED;
74       HandleDisplayHotplugEvent(static_cast<uint64_t>(display_id), false);
75       break;
76     case DrmHwc::kConnected:
77       event = common::DisplayHotplugEvent::CONNECTED;
78       HandleDisplayHotplugEvent(static_cast<uint64_t>(display_id), true);
79       break;
80     case DrmHwc::kLinkTrainingFailed:
81       event = common::DisplayHotplugEvent::ERROR_INCOMPATIBLE_CABLE;
82       break;
83   }
84   composer_callback_->onHotplugEvent(static_cast<int64_t>(display_id), event);
85 }
86 
87 #else
88 
SendHotplugEventToClient(hwc2_display_t display_id,DrmHwc::DisplayStatus display_status)89 void DrmHwcThree::SendHotplugEventToClient(
90     hwc2_display_t display_id, DrmHwc::DisplayStatus display_status) {
91   bool connected = display_status != DrmHwc::kDisconnected;
92   HandleDisplayHotplugEvent(static_cast<uint64_t>(display_id), connected);
93   composer_callback_->onHotplug(static_cast<int64_t>(display_id), connected);
94 }
95 
96 #endif
97 
CleanDisplayResources(uint64_t display_id)98 void DrmHwcThree::CleanDisplayResources(uint64_t display_id) {
99   DEBUG_FUNC();
100   HwcDisplay* display = GetDisplay(display_id);
101   if (display == nullptr) {
102     return;
103   }
104 
105   display->SetPowerMode(static_cast<int32_t>(PowerMode::OFF));
106 
107   size_t cache_size = 0;
108   auto err = composer_resources_->GetDisplayClientTargetCacheSize(display_id,
109                                                                   &cache_size);
110   if (err != hwc3::Error::kNone) {
111     ALOGE("%s: Could not clear target buffer cache for display: %" PRIu64,
112           __func__, display_id);
113     return;
114   }
115 
116   for (size_t slot = 0; slot < cache_size; slot++) {
117     buffer_handle_t buffer_handle = nullptr;
118     auto buf_releaser = ComposerResources::CreateResourceReleaser(true);
119 
120     Buffer buf{};
121     buf.slot = static_cast<int32_t>(slot);
122     err = composer_resources_->GetDisplayClientTarget(display_id, buf,
123                                                       &buffer_handle,
124                                                       buf_releaser.get());
125     if (err != hwc3::Error::kNone) {
126       continue;
127     }
128 
129     err = Hwc2toHwc3Error(
130         display->SetClientTarget(buffer_handle, -1,
131                                  static_cast<int32_t>(
132                                      common::Dataspace::UNKNOWN),
133                                  {}));
134     if (err != hwc3::Error::kNone) {
135       ALOGE(
136           "%s: Could not clear slot %zu of the target buffer cache for "
137           "display %" PRIu64,
138           __func__, slot, display_id);
139     }
140   }
141 }
142 
HandleDisplayHotplugEvent(uint64_t display_id,bool connected)143 void DrmHwcThree::HandleDisplayHotplugEvent(uint64_t display_id,
144                                             bool connected) {
145   DEBUG_FUNC();
146   if (!connected) {
147     composer_resources_->RemoveDisplay(display_id);
148     Displays().erase(display_id);
149     return;
150   }
151 
152   if (composer_resources_->HasDisplay(display_id)) {
153     /* Cleanup existing display resources */
154     CleanDisplayResources(display_id);
155     composer_resources_->RemoveDisplay(display_id);
156     Displays().erase(display_id);
157   }
158   composer_resources_->AddPhysicalDisplay(display_id);
159 }
160 
161 }  // namespace aidl::android::hardware::graphics::composer3::impl
162