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