1 /*
2 * Copyright (c) 2021-2023 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
16 #include "hi_gbm.h"
17 #include <cerrno>
18 #include <cstring>
19 #include <cstdlib>
20 #include <fcntl.h>
21 #include <xf86drm.h>
22 #include <xf86drmMode.h>
23 #include <drm_fourcc.h>
24 #include <securec.h>
25 #include "display_log.h"
26 #include "hi_gbm_internal.h"
27
28 namespace OHOS {
29 namespace HDI {
30 namespace DISPLAY {
31 #ifdef ROCKCHIP_CMA
32 #define ROCKCHIP_BO_CONTIG (1 << 0)
33 #endif
34
35 using PlaneLayoutInfo = struct {
36 uint32_t numPlanes;
37 uint32_t radio[MAX_PLANES];
38 };
39
40 using FormatInfo = struct {
41 uint32_t format;
42 uint32_t bitsPerPixel; // bits per pixel for first plane
43 const PlaneLayoutInfo *planes;
44 };
45
46 static const PlaneLayoutInfo YUV_420SP_LAYOUT = {
47 .numPlanes = 2,
48 .radio = { 4, 2 },
49 };
50
51 static const PlaneLayoutInfo YUV_420P_LAYOUT = {
52 .numPlanes = 3,
53 .radio = { 4, 1, 1 },
54 };
55
56 static const PlaneLayoutInfo YUV_422SP_LAYOUT = {
57 .numPlanes = 2,
58 .radio = { 4, 4 },
59 };
60
61 static const PlaneLayoutInfo YUV_422P_LAYOUT = {
62 .numPlanes = 3,
63 .radio = { 4, 2, 2 },
64 };
65
GetFormatInfo(uint32_t format)66 static const FormatInfo *GetFormatInfo(uint32_t format)
67 {
68 static const FormatInfo FMT_INFOS[] = {
69 {DRM_FORMAT_RGBX8888, 32, nullptr}, {DRM_FORMAT_RGBA8888, 32, nullptr},
70 {DRM_FORMAT_BGRX8888, 32, nullptr}, {DRM_FORMAT_BGRA8888, 32, nullptr},
71 {DRM_FORMAT_RGB888, 24, nullptr}, {DRM_FORMAT_RGB565, 16, nullptr},
72 {DRM_FORMAT_BGRX4444, 16, nullptr}, {DRM_FORMAT_BGRA4444, 16, nullptr},
73 {DRM_FORMAT_RGBA4444, 16, nullptr}, {DRM_FORMAT_RGBX4444, 16, nullptr},
74 {DRM_FORMAT_BGRX5551, 16, nullptr}, {DRM_FORMAT_BGRA5551, 16, nullptr},
75 {DRM_FORMAT_NV12, 8, &YUV_420SP_LAYOUT}, {DRM_FORMAT_NV21, 8, &YUV_420SP_LAYOUT},
76 {DRM_FORMAT_NV16, 8, &YUV_422SP_LAYOUT}, {DRM_FORMAT_NV61, 8, &YUV_422SP_LAYOUT},
77 {DRM_FORMAT_YUV420, 8, &YUV_420P_LAYOUT}, {DRM_FORMAT_YVU420, 8, &YUV_420P_LAYOUT},
78 {DRM_FORMAT_YUV422, 8, &YUV_422P_LAYOUT}, {DRM_FORMAT_YVU422, 8, &YUV_422P_LAYOUT},
79 };
80
81 for (uint32_t i = 0; i < sizeof(FMT_INFOS) / sizeof(FormatInfo); i++) {
82 if (FMT_INFOS[i].format == format) {
83 return &FMT_INFOS[i];
84 }
85 }
86 DISPLAY_LOGE("the format can not support");
87 return nullptr;
88 }
89
InitGbmBo(struct gbm_bo * bo,const struct drm_mode_create_dumb * dumb)90 void InitGbmBo(struct gbm_bo *bo, const struct drm_mode_create_dumb *dumb)
91 {
92 DISPLAY_CHK_RETURN_NOT_VALUE((dumb == nullptr), DISPLAY_LOGE("dumb is null"));
93 DISPLAY_CHK_RETURN_NOT_VALUE((bo == nullptr), DISPLAY_LOGE("bo is null"));
94 bo->stride = dumb->pitch;
95 bo->size = dumb->size;
96 bo->handle = dumb->handle;
97 }
98
AdjustStrideFromFormat(uint32_t format,uint32_t height)99 static uint32_t AdjustStrideFromFormat(uint32_t format, uint32_t height)
100 {
101 uint32_t tmpHeight = height;
102 const FormatInfo *fmtInfo = GetFormatInfo(format);
103 if ((fmtInfo != nullptr) && (fmtInfo->planes != nullptr)) {
104 uint32_t sum = fmtInfo->planes->radio[0];
105 for (uint32_t i = 1; (i < fmtInfo->planes->numPlanes) && (i < MAX_PLANES); i++) {
106 sum += fmtInfo->planes->radio[i];
107 }
108 if (sum > 0) {
109 tmpHeight = DIV_ROUND_UP((height * sum), fmtInfo->planes->radio[0]);
110 }
111 DISPLAY_LOGD("height adjust to : %{public}d", tmpHeight);
112 }
113 return tmpHeight;
114 }
115
HdiGbmBoCreate(struct gbm_device * gbm,uint32_t width,uint32_t height,uint32_t format,uint32_t usage)116 struct gbm_bo *HdiGbmBoCreate(struct gbm_device *gbm, uint32_t width, uint32_t height, uint32_t format,
117 uint32_t usage)
118 {
119 DISPLAY_UNUSED(usage);
120 int ret;
121 struct gbm_bo *bo;
122 struct drm_mode_create_dumb dumb = { 0 };
123 const FormatInfo *fmtInfo = GetFormatInfo(format);
124 DISPLAY_CHK_RETURN((fmtInfo == nullptr), nullptr,
125 DISPLAY_LOGE("formt: 0x%{public}x can not get layout info", format));
126 bo = (struct gbm_bo *)calloc(1, sizeof(struct gbm_bo));
127 DISPLAY_CHK_RETURN((bo == nullptr), nullptr, DISPLAY_LOGE("gbm bo create fialed no memery"));
128 (void)memset_s(bo, sizeof(struct gbm_bo), 0, sizeof(struct gbm_bo));
129 bo->width = width;
130 bo->height = height;
131 bo->gbm = gbm;
132 bo->format = format;
133 // init create_dumb
134 dumb.height = ALIGN_UP(AdjustStrideFromFormat(format, height), HEIGHT_ALIGN);
135 dumb.width = ALIGN_UP(width, WIDTH_ALIGN);
136 dumb.flags = 0;
137 dumb.bpp = fmtInfo->bitsPerPixel;
138 ret = drmIoctl(gbm->fd, DRM_IOCTL_MODE_CREATE_DUMB, &dumb);
139 DISPLAY_LOGD("fmt 0x%{public}x create dumb width: %{public}d height: %{public}d bpp: %{public}u pitch"
140 "%{public}d size %{public}llu",
141 format, dumb.width, dumb.height, dumb.bpp, dumb.pitch, dumb.size);
142 DISPLAY_CHK_RETURN((ret != 0), nullptr, DISPLAY_LOGE("DRM_IOCTL_MODE_CREATE_DUMB failed errno %{public}d", errno));
143 InitGbmBo(bo, &dumb);
144 DISPLAY_LOGD(
145 "fmt 0x%{public}x create dumb width: %{public}d height: %{public}d stride %{public}d size %{public}u", format,
146 bo->width, bo->height, bo->stride, bo->size);
147 return bo;
148 }
149
HdiGbmCreateDevice(int fd)150 struct gbm_device *HdiGbmCreateDevice(int fd)
151 {
152 struct gbm_device *gbm = (struct gbm_device *)calloc(1, sizeof(struct gbm_device));
153 DISPLAY_CHK_RETURN((gbm == nullptr), nullptr, DISPLAY_LOGE("memory calloc failed"));
154 gbm->fd = fd;
155 return gbm;
156 }
157
HdiGbmDeviceDestroy(struct gbm_device * gbm)158 void HdiGbmDeviceDestroy(struct gbm_device *gbm)
159 {
160 free(gbm);
161 }
162
HdiGbmBoGetStride(struct gbm_bo * bo)163 uint32_t HdiGbmBoGetStride(struct gbm_bo *bo)
164 {
165 DISPLAY_CHK_RETURN((bo == nullptr), 0, DISPLAY_LOGE("the bo is null"));
166 return bo->stride;
167 }
168
HdiGbmBoGetWidth(struct gbm_bo * bo)169 uint32_t HdiGbmBoGetWidth(struct gbm_bo *bo)
170 {
171 DISPLAY_CHK_RETURN((bo == nullptr), 0, DISPLAY_LOGE("the bo is null"));
172 return bo->width;
173 }
174
HdiGbmBoGetHeight(struct gbm_bo * bo)175 uint32_t HdiGbmBoGetHeight(struct gbm_bo *bo)
176 {
177 DISPLAY_CHK_RETURN((bo == nullptr), 0, DISPLAY_LOGE("the bo is null"));
178 return bo->height;
179 }
180
HdiGbmBoGetSize(struct gbm_bo * bo)181 uint32_t HdiGbmBoGetSize(struct gbm_bo *bo)
182 {
183 DISPLAY_CHK_RETURN((bo == nullptr), 0, DISPLAY_LOGE("the bo is null"));
184 return bo->size;
185 }
186
HdiGbmBoDestroy(struct gbm_bo * bo)187 void HdiGbmBoDestroy(struct gbm_bo *bo)
188 {
189 int ret;
190 DISPLAY_CHK_RETURN_NOT_VALUE((bo == nullptr), DISPLAY_LOGE("the bo is null"));
191 struct drm_mode_destroy_dumb dumb = { 0 };
192 dumb.handle = bo->handle;
193 ret = drmIoctl(bo->gbm->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dumb);
194 DISPLAY_CHK_RETURN_NOT_VALUE((ret), DISPLAY_LOGE("dumb buffer destroy failed errno %{public}d", errno));
195 free(bo);
196 }
197
HdiGbmBoGetFd(struct gbm_bo * bo)198 int HdiGbmBoGetFd(struct gbm_bo *bo)
199 {
200 int fd;
201 int ret = drmPrimeHandleToFD(bo->gbm->fd, bo->handle, DRM_CLOEXEC | DRM_RDWR, &fd);
202 DISPLAY_CHK_RETURN((ret), -1,
203 DISPLAY_LOGE("drmPrimeHandleToFD failed ret: %{public}d errno: %{public}d", ret, errno));
204 return fd;
205 }
206 } // namespace DISPLAY
207 } // namespace HDI
208 } // namespace OHOS
209