xref: /OK3568_Linux_fs/external/linux-rga/samples/utils/allocator/drm_alloc.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright (C) 2022  Rockchip Electronics Co., Ltd.
3  * Authors:
4  *     Randall zhuo <randall.zhuo@rock-chips.com>
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #if defined (__arm__) || defined (__aarch64__)
20 #include <stdint.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/fcntl.h> // open function
25 #include <unistd.h>    // close function
26 #include <errno.h>
27 #include <sys/mman.h>
28 #include <dlfcn.h>
29 
30 #include <linux/input.h>
31 #include "libdrm/drm_fourcc.h"
32 #include "xf86drm.h"
33 
34 typedef int(* DRM_IOCTL)(int fd, unsigned long request, void *arg);
35 static DRM_IOCTL drmIoctl_func = NULL;
36 static void *drm_handle = NULL;
37 static int drm_fd = -1;
38 
39 struct drm_rockchip_gem_phys {
40     uint32_t handle;
41     uint32_t phy_addr;
42 };
43 
44 #define DRM_ROCKCHIP_GEM_GET_PHYS   0x04
45 #define DRM_IOCTL_ROCKCHIP_GEM_GET_PHYS     DRM_IOWR(DRM_COMMAND_BASE + \
46         DRM_ROCKCHIP_GEM_GET_PHYS, struct drm_rockchip_gem_phys)
47 
48 
drm_init()49 static int drm_init()
50 {
51     static const char *card = "/dev/dri/card0";
52     int flag = O_RDWR;
53     int drm_fd = -1;
54 
55     drm_fd = open(card, flag);
56     if (drm_fd < 0)
57     {
58         printf("failed to open %s\n", card);
59         return -1;
60     }
61     return drm_fd;
62 }
63 
drm_deinit(int drm_fd)64 static void drm_deinit(int drm_fd)
65 {
66     if (drm_fd > 0)
67     {
68         close(drm_fd);
69     }
70 }
71 
drm_buf_alloc(int TexWidth,int TexHeight,int bpp,int * fd,int * handle,size_t * actual_size,int flags=0)72 void *drm_buf_alloc(int TexWidth, int TexHeight, int bpp, int *fd,  int *handle, size_t *actual_size, int flags=0)
73 {
74     int ret;
75     char *map = NULL;
76 
77     void *vir_addr = NULL;
78     struct drm_prime_handle fd_args;
79     struct drm_mode_map_dumb mmap_arg;
80     struct drm_mode_destroy_dumb destory_arg;
81 
82     struct drm_mode_create_dumb alloc_arg;
83 
84     if ((drm_fd < 0) || (drmIoctl_func == NULL)) {
85         return NULL;
86     }
87 
88     memset(&alloc_arg, 0, sizeof(alloc_arg));
89     alloc_arg.bpp = bpp;
90     alloc_arg.width = TexWidth;
91     alloc_arg.height = TexHeight;
92     alloc_arg.flags = flags;
93 
94     //获取handle和size
95     ret = drmIoctl_func(drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &alloc_arg);
96     if (ret)
97     {
98         printf("failed to create dumb buffer: %s\n", strerror(errno));
99         return NULL;
100     }
101     if (handle != NULL)
102     {
103         *handle = alloc_arg.handle;
104     }
105     if (actual_size != NULL)
106     {
107         *actual_size = alloc_arg.size;
108     }
109 
110     int pagesize = sysconf(_SC_PAGESIZE);
111 #if 1
112     printf("pagesize is %d\n", pagesize);
113     printf("create width=%u, height=%u, bpp=%u, size=%lu dumb buffer\n", alloc_arg.width, alloc_arg.height, alloc_arg.bpp, (unsigned long)alloc_arg.size);
114     printf("out handle= %d\n", alloc_arg.handle);
115 #endif
116     //获取fd
117     memset(&fd_args, 0, sizeof(fd_args));
118     fd_args.fd = -1;
119     fd_args.handle = alloc_arg.handle;
120     fd_args.flags = 0;
121 
122     ret = drmIoctl_func(drm_fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &fd_args);
123     if (ret)
124     {
125         printf("rk-debug handle_to_fd failed ret=%d,err=%s, handle=%x \n", ret, strerror(errno), fd_args.handle);
126         return NULL;
127     }
128 
129     if (fd != NULL)
130     {
131         *fd = fd_args.fd;
132     }
133 
134     //获取虚拟地址
135     memset(&mmap_arg, 0, sizeof(mmap_arg));
136     mmap_arg.handle = alloc_arg.handle;
137 
138     ret = drmIoctl_func(drm_fd, DRM_IOCTL_MODE_MAP_DUMB, &mmap_arg);
139     if (ret)
140     {
141         printf("failed to create map dumb: %s\n", strerror(errno));
142         vir_addr = NULL;
143         goto destory_dumb;
144     }
145 
146     vir_addr = map = (char *)mmap(0, alloc_arg.size, PROT_READ | PROT_WRITE, MAP_SHARED, drm_fd, mmap_arg.offset);
147     if (map == MAP_FAILED)
148     {
149         printf("failed to mmap buffer: %s\n", strerror(errno));
150         vir_addr = NULL;
151         goto destory_dumb;
152     }
153     return vir_addr;
154 
155 destory_dumb:
156     memset(&destory_arg, 0, sizeof(destory_arg));
157     destory_arg.handle = alloc_arg.handle;
158     ret = drmIoctl_func(drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destory_arg);
159     return vir_addr;
160 }
161 
drm_buf_destroy(int buf_fd,int handle,void * drm_buf,size_t size)162 int drm_buf_destroy(int buf_fd, int handle, void *drm_buf, size_t size)
163 {
164     int ret = -1;
165 
166     if ((drm_fd < 0) || (drmIoctl_func == NULL)) {
167         return -1;
168     }
169 
170     if (drm_buf == NULL)
171     {
172         return -1;
173     }
174 
175     munmap(drm_buf, size);
176 
177     struct drm_mode_destroy_dumb destory_arg;
178     memset(&destory_arg, 0, sizeof(destory_arg));
179     destory_arg.handle = handle;
180 
181     ret = drmIoctl_func(drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destory_arg);
182     if (ret)
183     {
184         printf("failed to destory dumb %d, error=%s\n", ret, strerror(errno));
185     }
186 
187     if (buf_fd > 0)
188     {
189         close(buf_fd);
190     }
191 
192     return ret;
193 }
194 
drm_buf_get_phy(int handle)195 uint32_t drm_buf_get_phy(int handle) {
196     struct drm_rockchip_gem_phys phys_arg;
197     phys_arg.handle = handle;
198     phys_arg.phy_addr = 0;
199 
200     int ret = drmIoctl_func(drm_fd, DRM_IOCTL_ROCKCHIP_GEM_GET_PHYS, &phys_arg);
201     if (ret)
202         printf("failed to get phy address: %s\n", strerror(errno));
203 
204     printf("get phys 0x%x\n", phys_arg.phy_addr);
205 
206     return phys_arg.phy_addr;
207 }
208 
load_drm()209 __attribute__((constructor)) static int load_drm() {
210     drm_fd =  drm_init();
211 
212     if (drm_fd < 0) {
213         return -1;
214     }
215 
216     drm_handle = dlopen("libdrm.so", RTLD_LAZY);
217 
218     if (!drm_handle) {
219         printf("[RKNN] Can not find libdrm.so\n");
220         drm_deinit(drm_fd);
221         return -1;
222     }
223 
224     drmIoctl_func = (DRM_IOCTL)dlsym(drm_handle, "drmIoctl");
225 
226     if (drmIoctl_func == NULL) {
227         dlclose(drm_handle);
228         drm_handle = NULL;
229         drm_deinit(drm_fd);
230         return -1;
231     }
232 
233     return 0;
234 }
235 
unload_drm()236 __attribute__((destructor)) static void unload_drm() {
237     if (drm_handle) {
238         dlclose(drm_handle);
239         drm_handle = NULL;
240     }
241 
242     drm_deinit(drm_fd);
243     drm_fd = -1;
244 }
245 
246 #if 0
247 int main_(){
248   void *drm_buf = NULL;
249   int drm_fd = -1;
250   int out_fd;
251   unsigned int handle;
252   int width = 224;
253   int height = 224;
254   int channel = 3;
255   int size = width*height*channel;
256   int actual_size=0;
257   // DRM alloc buffer
258   while(1){
259     drm_fd = drm_init();
260 
261     drm_buf = drm_buf_alloc(drm_fd,width,height,channel*8,&out_fd,&handle,&actual_size);
262     // unsigned char * buf = (unsigned char *) drm_buf;
263     // for(int i = 0;i<width*height;++i) {
264     //   printf("[%d] %d\n",i,(int)buf[i]);
265     // }
266     // printf("\n");
267 
268 
269     //free drm buffer
270     drm_buf_destroy(drm_fd,out_fd,handle,drm_buf,actual_size);
271   }
272   return 0;
273 
274 }
275 #endif
276 #endif
277 
278