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 #include <cerrno>
18 #include <mutex>
19 #include <sys/mman.h>
20 #include "buffer_log.h"
21 #include "v1_0/include/idisplay_buffer.h"
22
23 #define CHECK_INIT() \
24 do { \
25 if (g_displayBuffer == nullptr) { \
26 GSError ret = Init(); \
27 if (ret != GSERROR_OK) { \
28 return ret; \
29 } \
30 } \
31 } while (0)
32
33 #define CHECK_BUFFER(buffer) \
34 do { \
35 if ((buffer) == nullptr) { \
36 return GSERROR_INVALID_ARGUMENTS; \
37 } \
38 } while (0)
39
40 namespace OHOS {
41 namespace {
GenerateError(GSError err,GraphicDispErrCode code)42 GSError GenerateError(GSError err, GraphicDispErrCode code)
43 {
44 switch (code) {
45 case GRAPHIC_DISPLAY_SUCCESS: return static_cast<GSError>(err + 0);
46 case GRAPHIC_DISPLAY_FAILURE: return static_cast<GSError>(err + LOWERROR_FAILURE);
47 case GRAPHIC_DISPLAY_FD_ERR: return static_cast<GSError>(err + EBADF);
48 case GRAPHIC_DISPLAY_PARAM_ERR: return static_cast<GSError>(err + EINVAL);
49 case GRAPHIC_DISPLAY_NULL_PTR: return static_cast<GSError>(err + EINVAL);
50 case GRAPHIC_DISPLAY_NOT_SUPPORT: return static_cast<GSError>(err + EOPNOTSUPP);
51 case GRAPHIC_DISPLAY_NOMEM: return static_cast<GSError>(err + ENOMEM);
52 case GRAPHIC_DISPLAY_SYS_BUSY: return static_cast<GSError>(err + EBUSY);
53 case GRAPHIC_DISPLAY_NOT_PERM: return static_cast<GSError>(err + EPERM);
54 default: break;
55 }
56 return static_cast<GSError>(err + LOWERROR_INVALID);
57 }
58
GenerateError(GSError err,int32_t code)59 inline GSError GenerateError(GSError err, int32_t code)
60 {
61 return GenerateError(err, static_cast<GraphicDispErrCode>(code));
62 }
63
64 using namespace OHOS::HDI::Display::Buffer::V1_0;
65 static std::unique_ptr<IDisplayBuffer> g_displayBuffer;
66
67 } // namespace
68
GetInstance()69 sptr<BufferManager> BufferManager::GetInstance()
70 {
71 static std::mutex mutex;
72 std::lock_guard<std::mutex> lock(mutex);
73 if (instance == nullptr) {
74 instance = new BufferManager();
75 }
76 return instance;
77 }
78
Init()79 GSError BufferManager::Init()
80 {
81 if (g_displayBuffer != nullptr) {
82 BLOGD("BufferManager has been initialized successfully.");
83 return GSERROR_OK;
84 }
85
86 g_displayBuffer.reset(IDisplayBuffer::Get());
87 if (g_displayBuffer == nullptr) {
88 BLOGE("IDisplayBuffer::Get return nullptr.");
89 return GSERROR_INTERNAL;
90 }
91 return GSERROR_OK;
92 }
93
Alloc(const BufferRequestConfig & config,sptr<SurfaceBuffer> & buffer)94 GSError BufferManager::Alloc(const BufferRequestConfig &config, sptr<SurfaceBuffer> &buffer)
95 {
96 CHECK_INIT();
97 CHECK_BUFFER(buffer);
98
99 BufferHandle *handle = nullptr;
100 int32_t allocWidth = config.width;
101 int32_t allocHeight = config.height;
102 AllocInfo info = {allocWidth, allocHeight, config.usage, config.format};
103 auto dret = g_displayBuffer->AllocMem(info, handle);
104 if (dret == GRAPHIC_DISPLAY_SUCCESS) {
105 buffer->SetBufferHandle(handle);
106 buffer->SetSurfaceBufferWidth(allocWidth);
107 buffer->SetSurfaceBufferHeight(allocHeight);
108 buffer->SetSurfaceBufferColorGamut(static_cast<GraphicColorGamut>(config.colorGamut));
109 buffer->SetSurfaceBufferTransform(static_cast<GraphicTransformType>(config.transform));
110 BLOGI("buffer handle w: %{public}d h: %{public}d t: %{public}d",
111 allocWidth, allocHeight, config.transform);
112 return GSERROR_OK;
113 }
114 BLOGW("Failed with %{public}d", dret);
115
116 return GenerateError(GSERROR_API_FAILED, dret);
117 }
118
Map(sptr<SurfaceBuffer> & buffer)119 GSError BufferManager::Map(sptr<SurfaceBuffer> &buffer)
120 {
121 CHECK_INIT();
122 CHECK_BUFFER(buffer);
123
124 BufferHandle *handle = buffer->GetBufferHandle();
125 if (handle == nullptr) {
126 return GSERROR_INVALID_ARGUMENTS;
127 }
128
129 void *virAddr = g_displayBuffer->Mmap(*handle);
130 if (virAddr == nullptr || virAddr == MAP_FAILED) {
131 return GSERROR_API_FAILED;
132 }
133 return GSERROR_OK;
134 }
135
Unmap(sptr<SurfaceBuffer> & buffer)136 GSError BufferManager::Unmap(sptr<SurfaceBuffer> &buffer)
137 {
138 CHECK_INIT();
139 CHECK_BUFFER(buffer);
140
141 if (buffer->GetVirAddr() == nullptr) {
142 return GSERROR_OK;
143 }
144
145 BufferHandle *handle = buffer->GetBufferHandle();
146 if (handle == nullptr) {
147 return GSERROR_INVALID_ARGUMENTS;
148 }
149
150 auto dret = g_displayBuffer->Unmap(*handle);
151 if (dret == GRAPHIC_DISPLAY_SUCCESS) {
152 handle->virAddr = nullptr;
153 return GSERROR_OK;
154 }
155 BLOGW("Failed with %{public}d", dret);
156 return GenerateError(GSERROR_API_FAILED, dret);
157 }
158
Unmap(BufferHandle * bufferHandle)159 GSError BufferManager::Unmap(BufferHandle *bufferHandle)
160 {
161 CHECK_INIT();
162 if (bufferHandle == nullptr) {
163 return GSERROR_OK;
164 }
165 if (bufferHandle->virAddr == nullptr) {
166 return GSERROR_OK;
167 }
168 auto dret = g_displayBuffer->Unmap(*bufferHandle);
169 if (dret == GRAPHIC_DISPLAY_SUCCESS) {
170 bufferHandle->virAddr = nullptr;
171 return GSERROR_OK;
172 }
173 BLOGW("Failed with %{public}d", dret);
174 return GenerateError(GSERROR_API_FAILED, dret);
175 }
176
FlushCache(sptr<SurfaceBuffer> & buffer)177 GSError BufferManager::FlushCache(sptr<SurfaceBuffer> &buffer)
178 {
179 CHECK_INIT();
180 CHECK_BUFFER(buffer);
181
182 BufferHandle *handle = buffer->GetBufferHandle();
183 if (handle == nullptr) {
184 return GSERROR_INVALID_ARGUMENTS;
185 }
186
187 auto dret = g_displayBuffer->FlushCache(*handle);
188 if (dret == GRAPHIC_DISPLAY_SUCCESS) {
189 return GSERROR_OK;
190 }
191 BLOGW("Failed with %{public}d", dret);
192 return GenerateError(GSERROR_API_FAILED, dret);
193 }
194
InvalidateCache(sptr<SurfaceBuffer> & buffer)195 GSError BufferManager::InvalidateCache(sptr<SurfaceBuffer> &buffer)
196 {
197 CHECK_INIT();
198 CHECK_BUFFER(buffer);
199
200 BufferHandle *handle = buffer->GetBufferHandle();
201 if (handle == nullptr) {
202 return GSERROR_INVALID_ARGUMENTS;
203 }
204
205 auto dret = g_displayBuffer->InvalidateCache(*handle);
206 if (dret == GRAPHIC_DISPLAY_SUCCESS) {
207 return GSERROR_OK;
208 }
209 BLOGW("Failed with %{public}d", dret);
210 return GenerateError(GSERROR_API_FAILED, dret);
211 }
212
Free(sptr<SurfaceBuffer> & buffer)213 GSError BufferManager::Free(sptr<SurfaceBuffer> &buffer)
214 {
215 CHECK_INIT();
216 CHECK_BUFFER(buffer);
217
218 BufferHandle *handle = buffer->GetBufferHandle();
219 buffer->SetBufferHandle(nullptr);
220 if (handle == nullptr) {
221 return GSERROR_INVALID_ARGUMENTS;
222 }
223
224 g_displayBuffer->FreeMem(*handle);
225 return GSERROR_OK;
226 }
227
IsSupportedAlloc(const std::vector<BufferVerifyAllocInfo> & infos,std::vector<bool> & supporteds)228 GSError BufferManager::IsSupportedAlloc(const std::vector<BufferVerifyAllocInfo> &infos,
229 std::vector<bool> &supporteds)
230 {
231 CHECK_INIT();
232 // mock data
233 supporteds.clear();
234 for (uint32_t index = 0; index < infos.size(); index++) {
235 if (infos[index].format == GRAPHIC_PIXEL_FMT_RGBA_8888 ||
236 infos[index].format == GRAPHIC_PIXEL_FMT_YCRCB_420_SP) {
237 supporteds.push_back(true);
238 } else {
239 supporteds.push_back(false);
240 }
241 }
242 return GSERROR_OK;
243 }
244 } // namespace OHOS
245