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