• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 g_yuv420SPLayout = {
47     .numPlanes = 2,
48     .radio = { 4, 2 },
49 };
50 
51 static const PlaneLayoutInfo g_yuv420PLayout = {
52     .numPlanes = 3,
53     .radio = { 4, 1, 1 },
54 };
55 
56 static const PlaneLayoutInfo g_yuv422SPLayout = {
57     .numPlanes = 2,
58     .radio = { 4, 4 },
59 };
60 
61 static const PlaneLayoutInfo g_yuv422PLayout = {
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 fmtInfos[] = {
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, &g_yuv420SPLayout}, {DRM_FORMAT_NV21, 8, &g_yuv420SPLayout},
76         {DRM_FORMAT_NV16, 8, &g_yuv422SPLayout},  {DRM_FORMAT_NV61, 8, &g_yuv422SPLayout},
77         {DRM_FORMAT_YUV420, 8, &g_yuv420PLayout}, {DRM_FORMAT_YVU420, 8, &g_yuv420PLayout},
78         {DRM_FORMAT_YUV422, 8, &g_yuv422PLayout}, {DRM_FORMAT_YVU422, 8, &g_yuv422PLayout},
79     };
80 
81     for (uint32_t i = 0; i < sizeof(fmtInfos) / sizeof(FormatInfo); i++) {
82         if (fmtInfos[i].format == format) {
83             return &fmtInfos[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 
AlignUp(uint32_t x,uint32_t a)99 static uint32_t AlignUp(uint32_t x, uint32_t a)
100 {
101     return ((((x) + ((a)-1)) / (a)) * (a));
102 }
103 
DivRoundUp(uint32_t n,uint32_t d)104 static uint32_t DivRoundUp(uint32_t n, uint32_t d)
105 {
106     return (((n) + (d)-1) / (d));
107 }
108 
AdjustStrideFromFormat(uint32_t format,uint32_t height)109 static uint32_t AdjustStrideFromFormat(uint32_t format, uint32_t height)
110 {
111     const FormatInfo *fmtInfo = GetFormatInfo(format);
112     uint32_t adjustheight = height;
113     if ((fmtInfo != nullptr) && (fmtInfo->planes != nullptr)) {
114         uint32_t sum = fmtInfo->planes->radio[0];
115         for (uint32_t i = 1; (i < fmtInfo->planes->numPlanes) && (i < MAX_PLANES); i++) {
116             sum += fmtInfo->planes->radio[i];
117         }
118         if (sum > 0) {
119             adjustheight = DivRoundUp((height * sum), fmtInfo->planes->radio[0]);
120         }
121         DISPLAY_LOGD("height adjust to : %{public}d", adjustheight);
122     }
123     return adjustheight;
124 }
125 
hdi_gbm_bo_create(struct gbm_device * gbm,uint32_t width,uint32_t height,uint32_t format,uint32_t usage)126 struct gbm_bo *hdi_gbm_bo_create(struct gbm_device *gbm, uint32_t width, uint32_t height,
127     uint32_t format, uint32_t usage)
128 {
129     int ret;
130     struct gbm_bo *bo = nullptr;
131     struct drm_mode_create_dumb dumb = { 0 };
132     const FormatInfo *fmtInfo = GetFormatInfo(format);
133     DISPLAY_CHK_RETURN((fmtInfo == nullptr), NULL, DISPLAY_LOGE("formt: 0x%{public}x can not get layout info", format));
134     bo = (struct gbm_bo *)calloc(1, sizeof(struct gbm_bo));
135     DISPLAY_CHK_RETURN((bo == nullptr), nullptr, DISPLAY_LOGE("gbm bo create fialed no memery %{public}d", usage));
136     (void)memset_s(bo, sizeof(struct gbm_bo), 0, sizeof(struct gbm_bo));
137     bo->width = width;
138     bo->height = height;
139     bo->gbm = gbm;
140     bo->format = format;
141     // init create_dumb
142     dumb.height = AlignUp(AdjustStrideFromFormat(format, height), HEIGHT_ALIGN);
143     dumb.width = AlignUp(width, WIDTH_ALIGN);
144     dumb.flags = 0;
145     dumb.bpp = fmtInfo->bitsPerPixel;
146     ret = drmIoctl(gbm->fd, DRM_IOCTL_MODE_CREATE_DUMB, &dumb);
147     DISPLAY_LOGI("fmt 0x%{public}x create dumb width: %{public}d  height: %{public}d bpp: %{public}u pitch %{public}d "
148         "size %{public}llu",
149         format, dumb.width, dumb.height, dumb.bpp, dumb.pitch, dumb.size);
150     DISPLAY_CHK_RETURN((ret != 0), nullptr, DISPLAY_LOGE("DRM_IOCTL_MODE_CREATE_DUMB failed errno %{public}d", errno));
151     InitGbmBo(bo, &dumb);
152     DISPLAY_LOGI(
153         "fmt 0x%{public}x create dumb width: %{public}d  height: %{public}d  stride %{public}d size %{public}u", format,
154         bo->width, bo->height, bo->stride, bo->size);
155     return bo;
156 }
157 
hdi_gbm_create_device(int fd)158 struct gbm_device *hdi_gbm_create_device(int fd)
159 {
160     struct gbm_device *gbm;
161     gbm = (struct gbm_device *)calloc(1, sizeof(struct gbm_device));
162     DISPLAY_CHK_RETURN((gbm == nullptr), nullptr, DISPLAY_LOGE("memory calloc failed"));
163     gbm->fd = fd;
164     return gbm;
165 }
166 
hdi_gbm_device_destroy(struct gbm_device * gbm)167 void hdi_gbm_device_destroy(struct gbm_device *gbm)
168 {
169     free(gbm);
170 }
171 
hdi_gbm_bo_get_stride(struct gbm_bo * bo)172 uint32_t hdi_gbm_bo_get_stride(struct gbm_bo *bo)
173 {
174     DISPLAY_CHK_RETURN((bo == nullptr), 0, DISPLAY_LOGE("the bo is null"));
175     return bo->stride;
176 }
177 
hdi_gbm_bo_get_width(struct gbm_bo * bo)178 uint32_t hdi_gbm_bo_get_width(struct gbm_bo *bo)
179 {
180     DISPLAY_CHK_RETURN((bo == nullptr), 0, DISPLAY_LOGE("the bo is null"));
181     return bo->width;
182 }
183 
hdi_gbm_bo_get_height(struct gbm_bo * bo)184 uint32_t hdi_gbm_bo_get_height(struct gbm_bo *bo)
185 {
186     DISPLAY_CHK_RETURN((bo == nullptr), 0, DISPLAY_LOGE("the bo is null"));
187     return bo->height;
188 }
189 
hdi_gbm_bo_get_size(struct gbm_bo * bo)190 uint32_t hdi_gbm_bo_get_size(struct gbm_bo *bo)
191 {
192     DISPLAY_CHK_RETURN((bo == nullptr), 0, DISPLAY_LOGE("the bo is null"));
193     return bo->size;
194 }
195 
hdi_gbm_bo_destroy(struct gbm_bo * bo)196 void hdi_gbm_bo_destroy(struct gbm_bo *bo)
197 {
198     int ret;
199     DISPLAY_CHK_RETURN_NOT_VALUE((bo == nullptr), DISPLAY_LOGE("the bo is null"));
200     struct drm_mode_destroy_dumb dumb = { 0 };
201     dumb.handle = bo->handle;
202     ret = drmIoctl(bo->gbm->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dumb);
203     DISPLAY_CHK_RETURN_NOT_VALUE((ret), DISPLAY_LOGE("dumb buffer destroy failed errno %{public}d", errno));
204     free(bo);
205 }
206 
hdi_gbm_bo_get_fd(struct gbm_bo * bo)207 int hdi_gbm_bo_get_fd(struct gbm_bo *bo)
208 {
209     int fd;
210 	int ret;
211     ret = drmPrimeHandleToFD(bo->gbm->fd, bo->handle, DRM_CLOEXEC | DRM_RDWR, &fd);
212     DISPLAY_CHK_RETURN((ret), -1, \
213         DISPLAY_LOGE("drmPrimeHandleToFD  failed ret: %{public}d  errno: %{public}d", ret, errno));
214     return fd;
215 }
216 } // namespace DISPLAY
217 } // namespace HDI
218 } // namespace OHOS
219