1 /*
2 * Copyright (c) 2022 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 #include "allocator.h"
16 #include <cinttypes>
17 #include "display_common.h"
18 namespace OHOS {
19 namespace HDI {
20 namespace DISPLAY {
DumpBufferHandle(BufferHandle & handle) const21 void Allocator::DumpBufferHandle(BufferHandle &handle) const
22 {
23 DISPLAY_LOGD("size %{public}d, width %{public}d height %{public}d stride %{public}d fd %{public}d format: %d "
24 "phy 0x%{public}" PRIx64 " usage 0x%{public}" PRIx64 " viraddr 0x%{public}p",
25 handle.size, handle.width, handle.height, handle.stride, handle.fd, handle.format, handle.phyAddr,
26 handle.usage, handle.virAddr);
27 }
28
IsYuv(PixelFormat format)29 bool Allocator::IsYuv(PixelFormat format)
30 {
31 switch (format) {
32 case PIXEL_FMT_YCBCR_420_P:
33 case PIXEL_FMT_YUV_422_I:
34 case PIXEL_FMT_YCBCR_422_SP:
35 case PIXEL_FMT_YCRCB_422_SP:
36 case PIXEL_FMT_YCBCR_420_SP:
37 case PIXEL_FMT_YCRCB_420_SP:
38 case PIXEL_FMT_YCBCR_422_P:
39 case PIXEL_FMT_YCRCB_422_P:
40 case PIXEL_FMT_YCRCB_420_P:
41 case PIXEL_FMT_YUYV_422_PKG:
42 case PIXEL_FMT_UYVY_422_PKG:
43 case PIXEL_FMT_YVYU_422_PKG:
44 case PIXEL_FMT_VYUY_422_PKG:
45 return true;
46 default:
47 return false;
48 }
49 }
50
UpdatePixelInfo(BufferInfo & bufferInfo)51 uint32_t Allocator::UpdatePixelInfo(BufferInfo &bufferInfo)
52 {
53 DISPLAY_LOGD("format is %{public}d", bufferInfo.format_);
54 if (IsYuv(bufferInfo.format_)) {
55 bufferInfo.bitsPerPixel_ = 8; // 8 bits per pixel
56 } else {
57 switch (bufferInfo.format_) {
58 case PIXEL_FMT_RGBX_8888:
59 case PIXEL_FMT_RGBA_8888:
60 case PIXEL_FMT_BGRX_8888:
61 case PIXEL_FMT_BGRA_8888:
62 bufferInfo.bitsPerPixel_ = 32; // 32 bits per pixel
63 break;
64 case PIXEL_FMT_RGB_888:
65 bufferInfo.bitsPerPixel_ = 24; // 24 bits per pixel
66 break;
67 case PIXEL_FMT_RGB_565:
68 case PIXEL_FMT_BGR_565:
69 case PIXEL_FMT_BGRX_4444:
70 case PIXEL_FMT_BGRA_4444:
71 case PIXEL_FMT_RGBA_4444:
72 case PIXEL_FMT_RGBX_4444:
73 case PIXEL_FMT_BGRX_5551:
74 case PIXEL_FMT_BGRA_5551:
75 bufferInfo.bitsPerPixel_ = 16; // 16 bits per pixel
76 break;
77 default:
78 DISPLAY_LOGE("the format can not support %{public}d", bufferInfo.format_);
79 return DISPLAY_NOT_SUPPORT;
80 }
81 }
82
83 bufferInfo.bytesPerPixel_ = bufferInfo.bitsPerPixel_ / BITS_PER_BYTES;
84 return DISPLAY_SUCCESS;
85 }
86
UpdateRGBStrideAndSize(BufferInfo & bufferInfo)87 int32_t Allocator::UpdateRGBStrideAndSize(BufferInfo &bufferInfo)
88 {
89 bufferInfo.widthStride_ = AlignUp(bufferInfo.width_, WIDTH_ALIGN);
90 bufferInfo.heightStride_ = AlignUp(bufferInfo.height_, HEIGHT_ALIGN);
91 bufferInfo.size_ = bufferInfo.widthStride_ * bufferInfo.heightStride_ * bufferInfo.bytesPerPixel_;
92 return DISPLAY_SUCCESS;
93 }
94
UpdateYuvStrideAndSize(BufferInfo & bufferInfo)95 int32_t Allocator::UpdateYuvStrideAndSize(BufferInfo &bufferInfo)
96 {
97 int32_t ret = DISPLAY_NOT_SUPPORT;
98 constexpr uint32_t UV_DIV_420 = 2;
99 DISPLAY_LOGD();
100 bufferInfo.widthStride_ = AlignUp(bufferInfo.width_, WIDTH_ALIGN);
101 bufferInfo.heightStride_ = AlignUp(bufferInfo.height_, HEIGHT_ALIGN);
102 switch (bufferInfo.format_) {
103 case PIXEL_FMT_YCBCR_420_P:
104 case PIXEL_FMT_YCBCR_422_SP:
105 case PIXEL_FMT_YCRCB_422_SP:
106 case PIXEL_FMT_YCBCR_420_SP:
107 case PIXEL_FMT_YCRCB_420_SP:
108 case PIXEL_FMT_YCRCB_420_P:
109 bufferInfo.heightStride_ = (bufferInfo.heightStride_ + bufferInfo.heightStride_ / UV_DIV_420);
110 ret = DISPLAY_SUCCESS;
111 break;
112 case PIXEL_FMT_YCBCR_422_P:
113 case PIXEL_FMT_YCRCB_422_P:
114 bufferInfo.heightStride_ = (bufferInfo.heightStride_ + bufferInfo.heightStride_);
115 bufferInfo.size_ = bufferInfo.widthStride_ * bufferInfo.heightStride_;
116 ret = DISPLAY_SUCCESS;
117 break;
118 default:
119 break;
120 }
121 return ret;
122 }
123
UpdateStrideAndSize(BufferInfo & bufferInfo)124 int32_t Allocator::UpdateStrideAndSize(BufferInfo &bufferInfo)
125 {
126 if (IsYuv(bufferInfo.format_)) {
127 return UpdateYuvStrideAndSize(bufferInfo);
128 } else {
129 return UpdateRGBStrideAndSize(bufferInfo);
130 }
131 }
132
ConvertToBufferInfo(BufferInfo & bufferInfo,const AllocInfo & info)133 int32_t Allocator::ConvertToBufferInfo(BufferInfo &bufferInfo, const AllocInfo &info)
134 {
135 DISPLAY_LOGD();
136 bufferInfo.width_ = info.width;
137 bufferInfo.height_ = info.height;
138 bufferInfo.format_ = info.format;
139 bufferInfo.usage_ = info.usage;
140 int32_t ret = UpdatePixelInfo(bufferInfo);
141 DISPLAY_CHK_RETURN(
142 (ret != DISPLAY_SUCCESS), DISPLAY_NOT_SUPPORT, DISPLAY_LOGE("failed to update pixel information"));
143 ret = UpdateStrideAndSize(bufferInfo);
144 DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_NOT_SUPPORT, DISPLAY_LOGE("failed to update stride and size"));
145 return DISPLAY_SUCCESS;
146 }
147
Init()148 int32_t Allocator::Init()
149 {
150 DISPLAY_LOGD();
151 return DISPLAY_SUCCESS;
152 }
153
AllocMem(const AllocInfo & info,BufferHandle ** handle)154 int32_t Allocator::AllocMem(const AllocInfo &info, BufferHandle **handle)
155 {
156 int ret;
157 DISPLAY_LOGD();
158 BufferInfo bufferInfo;
159 ret = ConvertToBufferInfo(bufferInfo, info);
160 DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_NOT_SUPPORT, DISPLAY_LOGE("failed to convert to bufferInfo"));
161
162 BufferHandle *priBuffer = (BufferHandle *)malloc(sizeof(BufferHandle));
163 DISPLAY_CHK_RETURN((priBuffer == nullptr), DISPLAY_NOT_SUPPORT, DISPLAY_LOGE("can not alloc memory"));
164 (void)memset_s(priBuffer, sizeof(BufferHandle), 0, sizeof(BufferHandle));
165 priBuffer->fd = -1;
166 priBuffer->width = bufferInfo.width_;
167 priBuffer->height = bufferInfo.height_;
168 priBuffer->stride = bufferInfo.widthStride_ * bufferInfo.bytesPerPixel_;
169 priBuffer->size = bufferInfo.size_;
170 priBuffer->format = bufferInfo.format_;
171 priBuffer->usage = bufferInfo.usage_;
172
173 ret = Allocate(bufferInfo, *priBuffer);
174 DumpBufferHandle(*priBuffer);
175 if (ret != DISPLAY_SUCCESS) {
176 DISPLAY_LOGE("AllocMem failed");
177 free(priBuffer);
178 priBuffer = nullptr;
179 return ret;
180 }
181 *handle = priBuffer;
182 return DISPLAY_SUCCESS;
183 }
184
Allocate(const BufferInfo & bufferInfo,BufferHandle & handle)185 int32_t Allocator::Allocate(const BufferInfo &bufferInfo, BufferHandle &handle)
186 {
187 DISPLAY_LOGE("AllocMem do not implement");
188 return DISPLAY_NOT_SUPPORT;
189 }
190
FreeMem(BufferHandle * handle)191 int32_t Allocator::FreeMem(BufferHandle *handle)
192 {
193 DISPLAY_LOGD();
194 DISPLAY_CHK_RETURN((handle == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("buffer is null"));
195 if (handle->fd >= 0) {
196 DISPLAY_LOGD("relase the fd is %{public}d", handle->fd);
197 close(handle->fd);
198 handle->fd = -1;
199 }
200 const uint32_t reserveFds = handle->reserveFds;
201 for (uint32_t i = 0; i < reserveFds; i++) {
202 if (handle->reserve[i] >= 0) {
203 DISPLAY_LOGD("relase the fd is %{public}d", handle->reserve[i]);
204 close(handle->reserve[i]);
205 handle->reserve[i] = -1;
206 }
207 }
208 free(handle);
209 return DISPLAY_SUCCESS;
210 }
211
DmaBufferSync(const BufferHandle & handle,uint64_t flag)212 int32_t Allocator::DmaBufferSync(const BufferHandle &handle, uint64_t flag)
213 {
214 if (handle.fd < 0) {
215 DISPLAY_LOGW("dmabuffer fd is invalid can not sync");
216 return DISPLAY_SUCCESS;
217 }
218
219 struct dma_buf_sync syncPrm = {0};
220 errno_t eok = memset_s(&syncPrm, sizeof(syncPrm), 0, sizeof(syncPrm));
221 DISPLAY_CHK_RETURN((eok != EOK), DISPLAY_PARAM_ERR, DISPLAY_LOGE("dma buffer sync memset_s failed"));
222 if (handle.usage & HBM_USE_CPU_WRITE) {
223 syncPrm.flags |= DMA_BUF_SYNC_WRITE;
224 }
225 if (handle.usage & HBM_USE_CPU_READ) {
226 syncPrm.flags |= DMA_BUF_SYNC_READ;
227 }
228 const int32_t retryMaxCount = 6;
229 int32_t retryCount = 0;
230 for (retryCount = 0; retryCount < retryMaxCount; retryCount++) {
231 int ret = ioctl(handle.fd, DMA_BUF_IOCTL_SYNC, &syncPrm);
232 if ((ret != -EAGAIN) && (ret != -EINTR)) {
233 break;
234 }
235 }
236
237 if (retryCount >= retryMaxCount) {
238 DISPLAY_LOGE("sync failed");
239 return DISPLAY_SYS_BUSY;
240 }
241 return DISPLAY_SUCCESS;
242 }
243
InvalidateCache(BufferHandle & handle)244 int32_t Allocator::InvalidateCache(BufferHandle &handle)
245 {
246 DISPLAY_LOGD();
247 return DmaBufferSync(handle, DMA_BUF_SYNC_END);
248 }
249
FlushCache(BufferHandle & handle)250 int32_t Allocator::FlushCache(BufferHandle &handle)
251 {
252 DISPLAY_LOGD();
253 return DmaBufferSync(handle, DMA_BUF_SYNC_START);
254 }
255
Mmap(BufferHandle & handle)256 void *Allocator::Mmap(BufferHandle &handle)
257 {
258 DISPLAY_LOGD();
259 void *virAddr = nullptr;
260 if (handle.virAddr != nullptr) {
261 DISPLAY_LOGW("the buffer has virtual addr");
262 return handle.virAddr;
263 }
264 virAddr = mmap(nullptr, handle.size, PROT_READ | PROT_WRITE, MAP_SHARED, handle.fd, 0);
265 if (virAddr == MAP_FAILED) {
266 DISPLAY_LOGE("mmap failed errno %{public}d, fd : %{public}d", errno, handle.fd);
267 handle.virAddr = nullptr;
268 return nullptr;
269 }
270 handle.virAddr = virAddr;
271 return virAddr;
272 }
273
Unmap(BufferHandle & handle)274 int32_t Allocator::Unmap(BufferHandle &handle)
275 {
276 if (handle.virAddr == nullptr) {
277 DISPLAY_LOGE("virAddr is nullptr , has not map the buffer");
278 return DISPLAY_PARAM_ERR;
279 }
280 int ret = munmap(handle.virAddr, handle.size);
281 if (ret != 0) {
282 DISPLAY_LOGE("munmap failed err: %{public}d", errno);
283 return DISPLAY_FAILURE;
284 }
285 handle.virAddr = nullptr;
286 return DISPLAY_SUCCESS;
287 }
288 } // namespace DISPLAY
289 } // namespace HDI
290 } // namespace OHOS