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