• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 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 #include "DrmDisplay.h"
18 
19 #include "DrmAtomicRequest.h"
20 
21 namespace aidl::android::hardware::graphics::composer3::impl {
22 namespace {
23 
24 template <typename T>
addressAsUint(T * pointer)25 uint64_t addressAsUint(T* pointer) {
26     return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(pointer));
27 }
28 
29 }  // namespace
30 
create(uint32_t id,std::unique_ptr<DrmConnector> connector,std::unique_ptr<DrmCrtc> crtc,std::unique_ptr<DrmPlane> plane,::android::base::borrowed_fd drmFd)31 std::unique_ptr<DrmDisplay> DrmDisplay::create(uint32_t id, std::unique_ptr<DrmConnector> connector,
32                                                std::unique_ptr<DrmCrtc> crtc,
33                                                std::unique_ptr<DrmPlane> plane,
34                                                ::android::base::borrowed_fd drmFd) {
35     if (!crtc) {
36         ALOGE("%s: invalid crtc.", __FUNCTION__);
37         return nullptr;
38     }
39     if (!connector) {
40         ALOGE("%s: invalid connector.", __FUNCTION__);
41         return nullptr;
42     }
43     if (!plane) {
44         ALOGE("%s: invalid plane.", __FUNCTION__);
45         return nullptr;
46     }
47 
48     if (connector->isConnected()) {
49         auto request = DrmAtomicRequest::create();
50         if (!request) {
51             ALOGE("%s: failed to create atomic request.", __FUNCTION__);
52             return nullptr;
53         }
54 
55         bool okay = true;
56         okay &= request->Set(connector->getId(), connector->getCrtcProperty(), crtc->getId());
57         okay &= request->Set(crtc->getId(), crtc->getActiveProperty(), 1);
58         okay &= request->Set(crtc->getId(), crtc->getModeProperty(),
59                              connector->getDefaultMode()->getBlobId());
60         okay &= request->Commit(drmFd);
61         if (!okay) {
62             ALOGE("%s: failed to set display mode.", __FUNCTION__);
63             return nullptr;
64         }
65     }
66 
67     return std::unique_ptr<DrmDisplay>(
68         new DrmDisplay(id, std::move(connector), std::move(crtc), std::move(plane)));
69 }
70 
flush(::android::base::borrowed_fd drmFd,::android::base::borrowed_fd inSyncFd,const std::shared_ptr<DrmBuffer> & buffer)71 std::tuple<HWC3::Error, ::android::base::unique_fd> DrmDisplay::flush(
72     ::android::base::borrowed_fd drmFd, ::android::base::borrowed_fd inSyncFd,
73     const std::shared_ptr<DrmBuffer>& buffer) {
74     std::unique_ptr<DrmAtomicRequest> request = DrmAtomicRequest::create();
75     if (!request) {
76         ALOGE("%s: failed to create atomic request.", __FUNCTION__);
77         return std::make_tuple(HWC3::Error::NoResources, ::android::base::unique_fd());
78     }
79 
80     int flushFenceFd = -1;
81 
82     bool okay = true;
83     okay &=
84         request->Set(mCrtc->getId(), mCrtc->getOutFenceProperty(), addressAsUint(&flushFenceFd));
85     okay &= request->Set(mPlane->getId(), mPlane->getCrtcProperty(), mCrtc->getId());
86     okay &= request->Set(mPlane->getId(), mPlane->getInFenceProperty(), inSyncFd.get());
87     okay &= request->Set(mPlane->getId(), mPlane->getFbProperty(), *buffer->mDrmFramebuffer);
88     okay &= request->Set(mPlane->getId(), mPlane->getCrtcXProperty(), 0);
89     okay &= request->Set(mPlane->getId(), mPlane->getCrtcYProperty(), 0);
90     okay &= request->Set(mPlane->getId(), mPlane->getCrtcWProperty(), buffer->mWidth);
91     okay &= request->Set(mPlane->getId(), mPlane->getCrtcHProperty(), buffer->mHeight);
92     okay &= request->Set(mPlane->getId(), mPlane->getSrcXProperty(), 0);
93     okay &= request->Set(mPlane->getId(), mPlane->getSrcYProperty(), 0);
94     okay &= request->Set(mPlane->getId(), mPlane->getSrcWProperty(), buffer->mWidth << 16);
95     okay &= request->Set(mPlane->getId(), mPlane->getSrcHProperty(), buffer->mHeight << 16);
96 
97     okay &= request->Commit(drmFd);
98     if (!okay) {
99         ALOGE("%s: failed to flush to display.", __FUNCTION__);
100         return std::make_tuple(HWC3::Error::NoResources, ::android::base::unique_fd());
101     }
102 
103     mPreviousBuffer = buffer;
104 
105     DEBUG_LOG("%s: submitted atomic update, flush fence:%d\n", __FUNCTION__, flushFenceFd);
106     return std::make_tuple(HWC3::Error::None, ::android::base::unique_fd(flushFenceFd));
107 }
108 
onConnect(::android::base::borrowed_fd drmFd)109 bool DrmDisplay::onConnect(::android::base::borrowed_fd drmFd) {
110     DEBUG_LOG("%s: display:%" PRIu32, __FUNCTION__, mId);
111 
112     auto request = DrmAtomicRequest::create();
113     if (!request) {
114         ALOGE("%s: display:%" PRIu32 " failed to create atomic request.", __FUNCTION__, mId);
115         return false;
116     }
117 
118     bool okay = true;
119     okay &= request->Set(mConnector->getId(), mConnector->getCrtcProperty(), mCrtc->getId());
120     okay &= request->Set(mCrtc->getId(), mCrtc->getActiveProperty(), 1);
121     okay &= request->Set(mCrtc->getId(), mCrtc->getModeProperty(),
122                          mConnector->getDefaultMode()->getBlobId());
123 
124     okay &= request->Commit(drmFd);
125     if (!okay) {
126         ALOGE("%s: display:%" PRIu32 " failed to set mode.", __FUNCTION__, mId);
127         return false;
128     }
129 
130     return true;
131 }
132 
onDisconnect(::android::base::borrowed_fd drmFd)133 bool DrmDisplay::onDisconnect(::android::base::borrowed_fd drmFd) {
134     DEBUG_LOG("%s: display:%" PRIu32, __FUNCTION__, mId);
135 
136     auto request = DrmAtomicRequest::create();
137     if (!request) {
138         ALOGE("%s: display:%" PRIu32 " failed to create atomic request.", __FUNCTION__, mId);
139         return false;
140     }
141 
142     bool okay = true;
143     okay &= request->Set(mPlane->getId(), mPlane->getCrtcProperty(), 0);
144     okay &= request->Set(mPlane->getId(), mPlane->getFbProperty(), 0);
145 
146     okay &= request->Commit(drmFd);
147     if (!okay) {
148         ALOGE("%s: display:%" PRIu32 " failed to set mode", __FUNCTION__, mId);
149     }
150 
151     mPreviousBuffer.reset();
152 
153     return okay;
154 }
155 
checkAndHandleHotplug(::android::base::borrowed_fd drmFd)156 DrmHotplugChange DrmDisplay::checkAndHandleHotplug(::android::base::borrowed_fd drmFd) {
157     DEBUG_LOG("%s: display:%" PRIu32, __FUNCTION__, mId);
158 
159     const bool oldConnected = mConnector->isConnected();
160     mConnector->update(drmFd);
161     const bool newConnected = mConnector->isConnected();
162 
163     if (oldConnected == newConnected) {
164         return DrmHotplugChange::kNoChange;
165     }
166 
167     if (newConnected) {
168         ALOGI("%s: display:%" PRIu32 " was connected.", __FUNCTION__, mId);
169         if (!onConnect(drmFd)) {
170             ALOGE("%s: display:%" PRIu32 " failed to connect.", __FUNCTION__, mId);
171         }
172         return DrmHotplugChange::kConnected;
173     } else {
174         ALOGI("%s: display:%" PRIu32 " was disconnected.", __FUNCTION__, mId);
175         if (!onDisconnect(drmFd)) {
176             ALOGE("%s: display:%" PRIu32 " failed to disconnect.", __FUNCTION__, mId);
177         }
178         return DrmHotplugChange::kDisconnected;
179     }
180 }
181 
182 }  // namespace aidl::android::hardware::graphics::composer3::impl
183