• 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},  {DRM_FORMAT_RGBA8888, 32,  NULL},
66         {DRM_FORMAT_BGRX8888,  32, NULL},  {DRM_FORMAT_BGRA8888, 32,  NULL},
67         {DRM_FORMAT_RGB888,    24, NULL},  {DRM_FORMAT_RGB565,   16,  NULL},
68         {DRM_FORMAT_BGRX4444,  16, NULL},  {DRM_FORMAT_BGRA4444, 16,  NULL},
69         {DRM_FORMAT_RGBA4444,  16, NULL},  {DRM_FORMAT_RGBX4444, 16,  NULL},
70         {DRM_FORMAT_BGRX5551,  16, NULL},  {DRM_FORMAT_BGRA5551, 16,  NULL},
71         {DRM_FORMAT_NV12, 8, &g_yuv420SPLayout}, {DRM_FORMAT_NV21, 8, &g_yuv420SPLayout},
72         {DRM_FORMAT_NV16, 8, &g_yuv422SPLayout},  {DRM_FORMAT_NV61, 8, &g_yuv422SPLayout},
73         {DRM_FORMAT_YUV420, 8, &g_yuv420PLayout}, {DRM_FORMAT_YVU420, 8, &g_yuv420PLayout},
74         {DRM_FORMAT_YUV422, 8, &g_yuv422PLayout}, {DRM_FORMAT_YVU422, 8, &g_yuv422PLayout},
75     };
76 
77     for (uint32_t i = 0; i < sizeof(fmtInfos) / sizeof(FormatInfo); i++) {
78         if (fmtInfos[i].format == format) {
79             return &fmtInfos[i];
80         }
81     }
82     DISPLAY_LOGE("the format can not support");
83     return NULL;
84 }
85 
InitGbmBo(struct gbm_bo * bo,const struct drm_mode_create_dumb * dumb)86 void InitGbmBo(struct gbm_bo *bo, const struct drm_mode_create_dumb *dumb)
87 {
88     DISPLAY_CHK_RETURN_NOT_VALUE((dumb == NULL), DISPLAY_LOGE("dumb is null"));
89     DISPLAY_CHK_RETURN_NOT_VALUE((bo == NULL), DISPLAY_LOGE("bo is null"));
90     bo->stride = dumb->pitch;
91     bo->size = dumb->size;
92     bo->handle = dumb->handle;
93 }
94 
AdjustStrideFromFormat(uint32_t format,uint32_t height)95 static uint32_t AdjustStrideFromFormat(uint32_t format, uint32_t height)
96 {
97     uint32_t tmpHeight = height;
98     const FormatInfo *fmtInfo = GetFormatInfo(format);
99     if ((fmtInfo != NULL) && (fmtInfo->planes != NULL)) {
100         uint32_t sum = fmtInfo->planes->radio[0];
101         for (uint32_t i = 1; (i < fmtInfo->planes->numPlanes) && (i < MAX_PLANES); i++) {
102             sum += fmtInfo->planes->radio[i];
103         }
104         if (sum > 0) {
105             tmpHeight = DIV_ROUND_UP((height * sum), fmtInfo->planes->radio[0]);
106         }
107         DISPLAY_DEBUGLOG("height adjust to : %{public}d", tmpHeight);
108     }
109     return tmpHeight;
110 }
111 
hdi_gbm_bo_create(struct gbm_device * gbm,uint32_t width,uint32_t height,uint32_t format,uint32_t usage)112 struct gbm_bo *hdi_gbm_bo_create(struct gbm_device *gbm, uint32_t width, uint32_t height, uint32_t format,
113     uint32_t usage)
114 {
115     DISPLAY_UNUSED(usage);
116     int ret;
117     struct gbm_bo *bo;
118     struct drm_mode_create_dumb dumb = { 0 };
119     const FormatInfo *fmtInfo = GetFormatInfo(format);
120     DISPLAY_CHK_RETURN((fmtInfo == NULL), NULL, DISPLAY_LOGE("formt: 0x%{public}x can not get layout info", format));
121     bo = (struct gbm_bo *)calloc(1, sizeof(struct gbm_bo));
122     DISPLAY_CHK_RETURN((bo == NULL), NULL, DISPLAY_LOGE("gbm bo create fialed no memery"));
123     (void)memset_s(bo, sizeof(struct gbm_bo), 0, sizeof(struct gbm_bo));
124     bo->width = width;
125     bo->height = height;
126     bo->gbm = gbm;
127     bo->format = format;
128     // init create_dumb
129     dumb.height = ALIGN_UP(height, HEIGHT_ALIGN);
130     dumb.width = ALIGN_UP(AdjustStrideFromFormat(format, width), WIDTH_ALIGN);
131     dumb.flags = 0;
132     dumb.bpp = fmtInfo->bitsPerPixel;
133     ret = drmIoctl(gbm->fd, DRM_IOCTL_MODE_CREATE_DUMB, &dumb);
134     DISPLAY_DEBUGLOG("fmt 0x%{public}x create dumb width: %{public}d  height: %{public}d bpp: %{public}u pitch"
135         "%{public}d size %{public}llu",
136         format, dumb.width, dumb.height, dumb.bpp, dumb.pitch, dumb.size);
137     DISPLAY_CHK_RETURN((ret != 0), NULL, DISPLAY_LOGE("DRM_IOCTL_MODE_CREATE_DUMB failed errno %{public}d", errno));
138     InitGbmBo(bo, &dumb);
139     DISPLAY_DEBUGLOG(
140         "fmt 0x%{public}x create dumb width: %{public}d  height: %{public}d  stride %{public}d size %{public}u", format,
141         bo->width, bo->height, bo->stride, bo->size);
142     return bo;
143 }
144 
hdi_gbm_create_device(int fd)145 struct gbm_device *hdi_gbm_create_device(int fd)
146 {
147     struct gbm_device *gbm;
148     gbm = (struct gbm_device *)calloc(1, sizeof(struct gbm_device));
149     DISPLAY_CHK_RETURN((gbm == NULL), NULL, DISPLAY_LOGE("memory calloc failed"));
150     gbm->fd = fd;
151     return gbm;
152 }
153 
hdi_gbm_device_destroy(struct gbm_device * gbm)154 void hdi_gbm_device_destroy(struct gbm_device *gbm)
155 {
156     free(gbm);
157 }
158 
hdi_gbm_bo_get_stride(struct gbm_bo * bo)159 uint32_t hdi_gbm_bo_get_stride(struct gbm_bo *bo)
160 {
161     DISPLAY_CHK_RETURN((bo == NULL), 0, DISPLAY_LOGE("the bo is null"));
162     return bo->stride;
163 }
164 
hdi_gbm_bo_get_width(struct gbm_bo * bo)165 uint32_t hdi_gbm_bo_get_width(struct gbm_bo *bo)
166 {
167     DISPLAY_CHK_RETURN((bo == NULL), 0, DISPLAY_LOGE("the bo is null"));
168     return bo->width;
169 }
170 
hdi_gbm_bo_get_height(struct gbm_bo * bo)171 uint32_t hdi_gbm_bo_get_height(struct gbm_bo *bo)
172 {
173     DISPLAY_CHK_RETURN((bo == NULL), 0, DISPLAY_LOGE("the bo is null"));
174     return bo->height;
175 }
176 
hdi_gbm_bo_destroy(struct gbm_bo * bo)177 void hdi_gbm_bo_destroy(struct gbm_bo *bo)
178 {
179     int ret;
180     DISPLAY_CHK_RETURN_NOT_VALUE((bo == NULL), DISPLAY_LOGE("the bo is null"));
181     struct drm_mode_destroy_dumb dumb = { 0 };
182     dumb.handle = bo->handle;
183     ret = drmIoctl(bo->gbm->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dumb);
184     DISPLAY_CHK_RETURN_NOT_VALUE((ret), DISPLAY_LOGE("dumb buffer destroy failed errno %{public}d", errno));
185     free(bo);
186 }
187 
hdi_gbm_bo_get_fd(struct gbm_bo * bo)188 int hdi_gbm_bo_get_fd(struct gbm_bo *bo)
189 {
190     int fd, ret;
191     ret = drmPrimeHandleToFD(bo->gbm->fd, bo->handle, DRM_CLOEXEC | DRM_RDWR, &fd);
192     DISPLAY_CHK_RETURN((ret), -1,
193         DISPLAY_LOGE("drmPrimeHandleToFD  failed ret: %{public}d  errno: %{public}d", ret, errno));
194     return fd;
195 }
196