1 /*
2 * Copyright (c) 2022 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 #include "drm_allocator.h"
16 #include <cinttypes>
17 #include <cerrno>
18 #include <fcntl.h>
19 #include <securec.h>
20 #include <xf86drm.h>
21 #include <xf86drmMode.h>
22 #include "display_common.h"
23 #include "drm_fourcc.h"
24 #include "hisilicon_drm.h"
25 namespace OHOS {
26 namespace HDI {
27 namespace DISPLAY {
Init()28 int32_t DrmAllocator::Init()
29 {
30 DISPLAY_LOGD();
31 int32_t ret;
32 drmFd_ = open(FILE_PATH, O_RDWR);
33 DISPLAY_CHK_RETURN((drmFd_ < 0), DISPLAY_FAILURE,
34 DISPLAY_LOGE("can not open drm file : %{public}s errno: %{public}d ", FILE_PATH, errno));
35 ret = drmDropMaster(drmFd_);
36 if (ret != 0) {
37 DISPLAY_LOGW("can not drop master");
38 }
39 return DISPLAY_SUCCESS;
40 }
41
Allocate(const BufferInfo & bufferInfo,BufferHandle & handle)42 int32_t DrmAllocator::Allocate(const BufferInfo &bufferInfo, BufferHandle &handle)
43 {
44 int32_t ret;
45 int32_t fd;
46 struct drm_mode_create_dumb dumb = {0};
47 // create_dumb
48 dumb.width = bufferInfo.widthStride_;
49 dumb.height = bufferInfo.heightStride_;
50 dumb.flags = 0;
51 dumb.bpp = bufferInfo.bitsPerPixel_;
52 DISPLAY_LOGD();
53 ret = drmIoctl(drmFd_, DRM_IOCTL_MODE_CREATE_DUMB, &dumb);
54 DISPLAY_LOGI("fmt 0x%{public}x create dumb width: %{public}d height: %{public}d bpp: %{public}u pitch %{public}d "
55 "size %{public}llu",
56 handle.format, dumb.width, dumb.height, dumb.bpp, dumb.pitch, dumb.size);
57 DISPLAY_CHK_RETURN(
58 (ret != 0), DISPLAY_FAILURE, DISPLAY_LOGE("DRM_IOCTL_MODE_CREATE_DUMB failed errno %{public}d", errno));
59
60 ret = drmPrimeHandleToFD(drmFd_, dumb.handle, DRM_CLOEXEC | DRM_RDWR, &fd);
61 DISPLAY_CHK_RETURN(
62 (ret != 0), DISPLAY_FAILURE, DISPLAY_LOGE("can not get fd from prime handle errno: %{public}d", errno));
63 handle.fd = fd;
64 handle.size = dumb.size;
65 handle.phyAddr = GetPhysicalAddr(handle.fd);
66
67 if ((handle.usage & HBM_USE_MEM_FB) != 0) {
68 handle.format = PIXEL_FMT_BGRA_8888;
69 DISPLAY_LOGI("drm Allocate set to PIXEL_FMT_BGRA_8888 for FB");
70 }
71
72 struct drm_mode_destroy_dumb destoryDumb = {0};
73 destoryDumb.handle = dumb.handle;
74 ret = drmIoctl(drmFd_, DRM_IOCTL_MODE_DESTROY_DUMB, &destoryDumb);
75 if (ret != 0) {
76 DISPLAY_LOGW("can not destroy dumb errno: %{public}d", errno);
77 }
78
79 return DISPLAY_SUCCESS;
80 }
81
GetPhysicalAddr(int primeFd)82 uint64_t DrmAllocator::GetPhysicalAddr(int primeFd)
83 {
84 struct DrmHisiliconPhyaddr args;
85 int ret;
86 DISPLAY_LOGD();
87 (void)memset_s(&args, sizeof(args), 0, sizeof(args));
88 args.fd = primeFd;
89 ret = ioctl(drmFd_, DRM_IOCTL_HISILICON_GEM_FD_TO_PHYADDR, &args);
90 if (ret != 0) {
91 DISPLAY_LOGE("DRM_IOCTL_HISILICON_GEM_FD_TO_PHYADDR return failed");
92 }
93 return args.phyaddr;
94 }
95
~DrmAllocator()96 DrmAllocator::~DrmAllocator()
97 {
98 DISPLAY_LOGD();
99 if (drmFd_ >= 0) {
100 close(drmFd_);
101 drmFd_ = -1;
102 }
103 }
104 } // namespace DISPLAY
105 } // namespace HDI
106 } // namespace OHOS