• 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                  "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