1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "buffer_manager.h"
17
18 #include <cerrno>
19 #include <mutex>
20 #include <sys/mman.h>
21
22 #include "buffer_log.h"
23
24 #define CHECK_INIT() \
25 do { \
26 if (displayGralloc_ == nullptr) { \
27 GSError ret = Init(); \
28 if (ret != GSERROR_OK) { \
29 return ret; \
30 } \
31 } \
32 } while (0)
33
34 #define CHECK_BUFFER(buffer) \
35 do { \
36 if ((buffer) == nullptr) { \
37 return GSERROR_INVALID_ARGUMENTS; \
38 } \
39 } while (0)
40
41 namespace OHOS {
42 namespace {
GenerateError(GSError err,DispErrCode code)43 GSError GenerateError(GSError err, DispErrCode code)
44 {
45 switch (code) {
46 case DISPLAY_SUCCESS: return static_cast<GSError>(err + 0);
47 case DISPLAY_FAILURE: return static_cast<GSError>(err + LOWERROR_FAILURE);
48 case DISPLAY_FD_ERR: return static_cast<GSError>(err + EBADF);
49 case DISPLAY_PARAM_ERR: return static_cast<GSError>(err + EINVAL);
50 case DISPLAY_NULL_PTR: return static_cast<GSError>(err + EINVAL);
51 case DISPLAY_NOT_SUPPORT: return static_cast<GSError>(err + EOPNOTSUPP);
52 case DISPLAY_NOMEM: return static_cast<GSError>(err + ENOMEM);
53 case DISPLAY_SYS_BUSY: return static_cast<GSError>(err + EBUSY);
54 case DISPLAY_NOT_PERM: return static_cast<GSError>(err + EPERM);
55 default: break;
56 }
57 return static_cast<GSError>(err + LOWERROR_INVALID);
58 }
59
GenerateError(GSError err,int32_t code)60 inline GSError GenerateError(GSError err, int32_t code)
61 {
62 return GenerateError(err, static_cast<DispErrCode>(code));
63 }
64 } // namespace
65
GetInstance()66 sptr<BufferManager> BufferManager::GetInstance()
67 {
68 static std::mutex mutex;
69 std::lock_guard<std::mutex> lock(mutex);
70 if (instance == nullptr) {
71 instance = new BufferManager();
72 }
73 return instance;
74 }
75
Init()76 GSError BufferManager::Init()
77 {
78 if (displayGralloc_ != nullptr) {
79 BLOGD("BufferManager has been initialized successfully.");
80 return GSERROR_OK;
81 }
82
83 displayGralloc_.reset(::OHOS::HDI::Display::V1_0::IDisplayGralloc::Get());
84 if (displayGralloc_ == nullptr) {
85 BLOGE("IDisplayGralloc::Get return nullptr.");
86 return GSERROR_INTERNAL;
87 }
88 return GSERROR_OK;
89 }
90
Alloc(const BufferRequestConfig & config,sptr<SurfaceBuffer> & buffer)91 GSError BufferManager::Alloc(const BufferRequestConfig &config, sptr<SurfaceBuffer> &buffer)
92 {
93 CHECK_INIT();
94 CHECK_BUFFER(buffer);
95
96 BufferHandle *handle = nullptr;
97 int32_t allocWidth = config.width;
98 int32_t allocHeight = config.height;
99 AllocInfo info = {allocWidth, allocHeight, config.usage, (PixelFormat)config.format};
100 auto dret = displayGralloc_->AllocMem(info, handle);
101 if (dret == DISPLAY_SUCCESS) {
102 buffer->SetBufferHandle(handle);
103 buffer->SetSurfaceBufferWidth(allocWidth);
104 buffer->SetSurfaceBufferHeight(allocHeight);
105 buffer->SetSurfaceBufferColorGamut(config.colorGamut);
106 buffer->SetSurfaceBufferTransform(config.transform);
107 BLOGI("buffer handle %{public}p w: %{public}d h: %{public}d t: %{public}d", handle,
108 allocWidth, allocHeight, config.transform);
109 return GSERROR_OK;
110 }
111 BLOGW("Failed with %{public}d", dret);
112
113 return GenerateError(GSERROR_API_FAILED, dret);
114 }
115
Map(sptr<SurfaceBuffer> & buffer)116 GSError BufferManager::Map(sptr<SurfaceBuffer> &buffer)
117 {
118 CHECK_INIT();
119 CHECK_BUFFER(buffer);
120
121 BufferHandle *handle = buffer->GetBufferHandle();
122 if (handle == nullptr) {
123 return GSERROR_INVALID_ARGUMENTS;
124 }
125
126 void *virAddr = displayGralloc_->Mmap(*handle);
127 if (virAddr == nullptr || virAddr == MAP_FAILED) {
128 return GSERROR_API_FAILED;
129 }
130 return GSERROR_OK;
131 }
132
Unmap(sptr<SurfaceBuffer> & buffer)133 GSError BufferManager::Unmap(sptr<SurfaceBuffer> &buffer)
134 {
135 CHECK_INIT();
136 CHECK_BUFFER(buffer);
137
138 if (buffer->GetVirAddr() == nullptr) {
139 return GSERROR_OK;
140 }
141
142 BufferHandle *handle = buffer->GetBufferHandle();
143 if (handle == nullptr) {
144 return GSERROR_INVALID_ARGUMENTS;
145 }
146
147 auto dret = displayGralloc_->Unmap(*handle);
148 if (dret == DISPLAY_SUCCESS) {
149 handle->virAddr = nullptr;
150 return GSERROR_OK;
151 }
152 BLOGW("Failed with %{public}d", dret);
153 return GenerateError(GSERROR_API_FAILED, dret);
154 }
155
Unmap(BufferHandle * bufferHandle)156 GSError BufferManager::Unmap(BufferHandle *bufferHandle)
157 {
158 CHECK_INIT();
159 if (bufferHandle == nullptr) {
160 return GSERROR_OK;
161 }
162 if (bufferHandle->virAddr == nullptr) {
163 return GSERROR_OK;
164 }
165 auto dret = displayGralloc_->Unmap(*bufferHandle);
166 if (dret == DISPLAY_SUCCESS) {
167 bufferHandle->virAddr = nullptr;
168 return GSERROR_OK;
169 }
170 BLOGW("Failed with %{public}d", dret);
171 return GenerateError(GSERROR_API_FAILED, dret);
172 }
173
FlushCache(sptr<SurfaceBuffer> & buffer)174 GSError BufferManager::FlushCache(sptr<SurfaceBuffer> &buffer)
175 {
176 CHECK_INIT();
177 CHECK_BUFFER(buffer);
178
179 BufferHandle *handle = buffer->GetBufferHandle();
180 if (handle == nullptr) {
181 return GSERROR_INVALID_ARGUMENTS;
182 }
183
184 auto dret = displayGralloc_->FlushCache(*handle);
185 if (dret == DISPLAY_SUCCESS) {
186 return GSERROR_OK;
187 }
188 BLOGW("Failed with %{public}d", dret);
189 return GenerateError(GSERROR_API_FAILED, dret);
190 }
191
InvalidateCache(sptr<SurfaceBuffer> & buffer)192 GSError BufferManager::InvalidateCache(sptr<SurfaceBuffer> &buffer)
193 {
194 CHECK_INIT();
195 CHECK_BUFFER(buffer);
196
197 BufferHandle *handle = buffer->GetBufferHandle();
198 if (handle == nullptr) {
199 return GSERROR_INVALID_ARGUMENTS;
200 }
201
202 auto dret = displayGralloc_->InvalidateCache(*handle);
203 if (dret == DISPLAY_SUCCESS) {
204 return GSERROR_OK;
205 }
206 BLOGW("Failed with %{public}d", dret);
207 return GenerateError(GSERROR_API_FAILED, dret);
208 }
209
Free(sptr<SurfaceBuffer> & buffer)210 GSError BufferManager::Free(sptr<SurfaceBuffer> &buffer)
211 {
212 CHECK_INIT();
213 CHECK_BUFFER(buffer);
214
215 BufferHandle *handle = buffer->GetBufferHandle();
216 buffer->SetBufferHandle(nullptr);
217 if (handle == nullptr) {
218 return GSERROR_INVALID_ARGUMENTS;
219 }
220
221 displayGralloc_->FreeMem(*handle);
222 return GSERROR_OK;
223 }
224
IsSupportedAlloc(const std::vector<BufferVerifyAllocInfo> & infos,std::vector<bool> & supporteds)225 GSError BufferManager::IsSupportedAlloc(const std::vector<BufferVerifyAllocInfo> &infos,
226 std::vector<bool> &supporteds)
227 {
228 CHECK_INIT();
229 // mock data
230 supporteds.clear();
231 for (uint32_t index = 0; index < infos.size(); index++) {
232 if (infos[index].format == GRAPHIC_PIXEL_FMT_RGBA_8888 ||
233 infos[index].format == GRAPHIC_PIXEL_FMT_YCRCB_420_SP) {
234 supporteds.push_back(true);
235 } else {
236 supporteds.push_back(false);
237 }
238 }
239 return GSERROR_OK;
240 }
241 } // namespace OHOS
242