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