xref: /OK3568_Linux_fs/external/linux-rga/samples/im2d_slt/sources/drm_alloc.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright (C) 2020 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 "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 
62     return drm_fd;
63 }
64 
drm_deinit(int drm_fd)65 static void drm_deinit(int drm_fd)
66 {
67     if (drm_fd > 0)
68     {
69         close(drm_fd);
70     }
71 }
72 
drm_buf_alloc(int TexWidth,int TexHeight,int bpp,int * fd,int * handle,size_t * actual_size,int flags=0)73 void *drm_buf_alloc(int TexWidth, int TexHeight, int bpp, int *fd,  int *handle, size_t *actual_size, int flags=0)
74 {
75     int ret;
76     char *map = NULL;
77 
78     void *vir_addr = NULL;
79     struct drm_prime_handle fd_args;
80     struct drm_mode_map_dumb mmap_arg;
81     struct drm_mode_destroy_dumb destory_arg;
82 
83     struct drm_mode_create_dumb alloc_arg;
84 
85     if ((drm_fd < 0) || (drmIoctl_func == NULL)) {
86         return NULL;
87     }
88 
89     memset(&alloc_arg, 0, sizeof(alloc_arg));
90     alloc_arg.bpp = bpp;
91     alloc_arg.width = TexWidth;
92     alloc_arg.height = TexHeight;
93     alloc_arg.flags = flags;
94 
95     //获取handle和size
96     ret = drmIoctl_func(drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &alloc_arg);
97     if (ret)
98     {
99         printf("failed to create dumb buffer: %s\n", strerror(errno));
100         return NULL;
101     }
102     if (handle != NULL)
103     {
104         *handle = alloc_arg.handle;
105     }
106     if (actual_size != NULL)
107     {
108         *actual_size = alloc_arg.size;
109     }
110 
111     // int pagesize = sysconf(_SC_PAGESIZE);
112 #if 0
113     printf("pagesize is %d\n", pagesize);
114     printf("create width=%u, height=%u, bpp=%u, size=%lu dumb buffer\n", alloc_arg.width, alloc_arg.height, alloc_arg.bpp, alloc_arg.size);
115     printf("out handle= %d\n", alloc_arg.handle);
116 #endif
117     //获取fd
118     memset(&fd_args, 0, sizeof(fd_args));
119     fd_args.fd = -1;
120     fd_args.handle = alloc_arg.handle;
121     fd_args.flags = 0;
122 
123     ret = drmIoctl_func(drm_fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &fd_args);
124     if (ret)
125     {
126         printf("rk-debug handle_to_fd failed ret=%d,err=%s, handle=%x \n", ret, strerror(errno), fd_args.handle);
127         return NULL;
128     }
129 
130     if (fd != NULL)
131     {
132         *fd = fd_args.fd;
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 
154     return vir_addr;
155 
156 destory_dumb:
157     memset(&destory_arg, 0, sizeof(destory_arg));
158     destory_arg.handle = alloc_arg.handle;
159     ret = drmIoctl_func(drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destory_arg);
160     return vir_addr;
161 }
162 
drm_buf_destroy(int buf_fd,int handle,void * drm_buf,size_t size)163 int drm_buf_destroy(int buf_fd, int handle, void *drm_buf, size_t size)
164 {
165     int ret = -1;
166 
167     if ((drm_fd < 0) || (drmIoctl_func == NULL)) {
168         return -1;
169     }
170 
171     if (drm_buf == NULL)
172     {
173         return -1;
174     }
175 
176     munmap(drm_buf, size);
177 
178     struct drm_mode_destroy_dumb destory_arg;
179     memset(&destory_arg, 0, sizeof(destory_arg));
180     destory_arg.handle = handle;
181 
182     ret = drmIoctl_func(drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destory_arg);
183     if (ret)
184     {
185         printf("failed to destory dumb %d, error=%s\n", ret, strerror(errno));
186     }
187 
188     if (buf_fd > 0)
189     {
190         close(buf_fd);
191     }
192 
193     return ret;
194 }
195 
drm_buf_get_phy(int handle)196 uint32_t drm_buf_get_phy(int handle) {
197     struct drm_rockchip_gem_phys phys_arg;
198     phys_arg.handle = handle;
199     phys_arg.phy_addr = 0;
200 
201     int ret = drmIoctl_func(drm_fd, DRM_IOCTL_ROCKCHIP_GEM_GET_PHYS, &phys_arg);
202     if (ret)
203         printf("failed to get phy address: %s\n", strerror(errno));
204 
205     printf("get phys 0x%x\n", phys_arg.phy_addr);
206 
207     return phys_arg.phy_addr;
208 }
209 
load_drm()210 __attribute__((constructor)) static int load_drm() {
211     drm_fd =  drm_init();
212 
213     if (drm_fd < 0) {
214         return -1;
215     }
216 
217     drm_handle = dlopen("libdrm.so", RTLD_LAZY);
218 
219     if (!drm_handle) {
220         printf("[RKNN] Can not find libdrm.so\n");
221         drm_deinit(drm_fd);
222         return -1;
223     }
224 
225     drmIoctl_func = (DRM_IOCTL)dlsym(drm_handle, "drmIoctl");
226 
227     if (drmIoctl_func == NULL) {
228         dlclose(drm_handle);
229         drm_handle = NULL;
230         drm_deinit(drm_fd);
231         return -1;
232     }
233 
234     return 0;
235 }
236 
unload_drm()237 __attribute__((destructor)) static void unload_drm() {
238     if (drm_handle) {
239         dlclose(drm_handle);
240         drm_handle = NULL;
241     }
242 
243     drm_deinit(drm_fd);
244     drm_fd = -1;
245 }
246 
247 #if 0
248 int main_(){
249   void *drm_buf = NULL;
250   int drm_fd = -1;
251   int out_fd;
252   unsigned int handle;
253   int width = 224;
254   int height = 224;
255   int channel = 3;
256   int size = width*height*channel;
257   int actual_size=0;
258   // DRM alloc buffer
259   while(1){
260     drm_fd = drm_init();
261 
262     drm_buf = drm_buf_alloc(drm_fd,width,height,channel*8,&out_fd,&handle,&actual_size);
263     // unsigned char * buf = (unsigned char *) drm_buf;
264     // for(int i = 0;i<width*height;++i) {
265     //   printf("[%d] %d\n",i,(int)buf[i]);
266     // }
267     // printf("\n");
268 
269 
270     //free drm buffer
271     drm_buf_destroy(drm_fd,out_fd,handle,drm_buf,actual_size);
272   }
273   return 0;
274 
275 }
276 #endif
277 #endif
278