• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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