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