1 #include <errno.h>
2 #include <fcntl.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <unistd.h>
7 #include <sys/ioctl.h>
8 #include <sys/mman.h>
9
10 #include <xf86drm.h>
11 #include <xf86drmMode.h>
12
map_fb(int fd,int handle,size_t size)13 static void *map_fb(int fd, int handle, size_t size) {
14 struct drm_prime_handle arg;
15 int ret;
16 void *ptr;
17
18 memset(&arg, 0, sizeof(arg));
19 arg.handle = handle;
20
21 ret = drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg);
22 if (ret) {
23 fprintf(stderr, "DRM_IOCTL_PRIME_HANDLE_TO_FD failed\n");
24 return NULL;
25 }
26
27 ptr = mmap(0, size, PROT_READ, MAP_SHARED, arg.fd, 0);
28 if (ptr == MAP_FAILED) {
29 fprintf(stderr, "mmap failed %s\n", strerror(errno));
30 return NULL;
31 }
32
33 return ptr;
34 }
35
get_fb_dmafd(int fd,int handle)36 static int get_fb_dmafd(int fd, int handle)
37 {
38 struct drm_prime_handle args;
39 int ret;
40
41 memset(&args, 0, sizeof(args));
42 args.fd = -1;
43 args.handle = handle;
44
45 ret = drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
46 if (ret)
47 return ret;
48
49 return args.fd;
50 }
51
destroy_dumb(int fd,int handle)52 static void destroy_dumb(int fd, int handle) {
53 struct drm_mode_destroy_dumb arg;
54
55 memset(&arg, 0, sizeof(arg));
56 arg.handle = handle;
57 drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &arg);
58 }
59
dump_fb(int fd,int fb_id)60 static int dump_fb(int fd, int fb_id) {
61 drmModeFBPtr fb = drmModeGetFB(fd, fb_id);
62 size_t size;
63 void *ptr;
64 int dmafd;
65
66 if (!fb) {
67 fprintf(stderr, "Failed to get framebuffer\n");
68 return -1;
69 }
70
71 size = fb->pitch * fb->height;
72
73 dmafd = get_fb_dmafd(fd, fb->handle);
74
75 fprintf(stderr, "fb handle=%d size=%dx%d(%d)\n",
76 fb->handle, fb->width, fb->height, fb->pitch);
77
78 ptr = map_fb(fd, fb->handle, size);
79 if (ptr) {
80 fprintf(stderr, "first pixel: %x\n", *((int *)ptr));
81 write(1, ptr, size);
82 munmap(ptr, size);
83 destroy_dumb(fd, fb->handle);
84 }
85
86 close(dmafd);
87 drmModeFreeFB(fb);
88 return 0;
89 }
90
get_crtc_fb(int fd,int crtc_id)91 static int get_crtc_fb(int fd, int crtc_id) {
92 drmModeCrtcPtr crtc;
93 int id;
94
95 crtc = drmModeGetCrtc(fd, crtc_id);
96 if (!crtc) {
97 fprintf(stderr, "Unknown CRTC %d\n", crtc_id);
98 return -1;
99 }
100
101 id = crtc->buffer_id;
102
103 drmModeFreeCrtc(crtc);
104 return id;
105 }
106
get_encoder_fb(int fd,int encoder_id)107 static int get_encoder_fb(int fd, int encoder_id) {
108 drmModeEncoderPtr encoder;
109 int id;
110
111 encoder = drmModeGetEncoder(fd, encoder_id);
112 if (!encoder) {
113 fprintf(stderr, "Unknown Encoder %d\n", encoder_id);
114 return -1;
115 }
116
117 id = get_crtc_fb(fd, encoder->crtc_id);
118
119 drmModeFreeEncoder(encoder);
120 return id;
121 }
122
get_connector_fb(int fd,int connector_id)123 static int get_connector_fb(int fd, int connector_id) {
124 drmModeConnector *connector;
125 int id;
126
127 connector = drmModeGetConnector(fd, connector_id);
128 if (!connector) {
129 fprintf(stderr, "Unknown Connector %d\n", connector_id);
130 return -1;
131 }
132
133 id = get_encoder_fb(fd, connector->encoder_id);
134
135 drmModeFreeConnector(connector);
136 return id;
137 }
138
get_plane_fb(int fd,int plane_id)139 static int get_plane_fb(int fd, int plane_id) {
140 drmModePlanePtr plane;
141 int id;
142
143 plane = drmModeGetPlane(fd, plane_id);
144 if (!plane) {
145 fprintf(stderr, "Unknown Plane %d\n", plane_id);
146 return -1;
147 }
148
149 id = plane->fb_id;
150
151 drmModeFreePlane(plane);
152 return id;
153 }
154
usage(const char * prog,int fd)155 static void usage(const char *prog, int fd) {
156 drmModeCrtcPtr crtc;
157 drmModeResPtr res;
158 int i;
159
160 res = drmModeGetResources(fd);
161
162 fprintf(stderr, "Usage:\n");
163 fprintf(stderr, "%s [--crtc|--connector|--plane|--fb] OBJ_ID > out\n",
164 prog);
165 fprintf(stderr, "Valid crtc:");
166 for (i = 0; i < res->count_crtcs; i++) {
167 crtc = drmModeGetCrtc(fd, res->crtcs[i]);
168 if (crtc && crtc->mode_valid)
169 fprintf(stderr, " %d", crtc->crtc_id);
170 drmModeFreeCrtc(crtc);
171 }
172 fprintf(stderr, "\n");
173
174 drmModeFreeResources(res);
175
176 exit(-1);
177 }
178
main(int argc,const char ** argv)179 int main(int argc, const char** argv) {
180 int id, fd;
181
182 fd = open("/dev/dri/card0", O_RDWR);
183 if (fd < 0) {
184 fprintf(stderr, "drm open failed\n");
185 return -1;
186 }
187 fcntl(fd, F_SETFD, FD_CLOEXEC);
188
189 // while (1) {
190
191 switch (argc) {
192 case 3:
193 id = atoi(argv[2]);
194
195 if (!strcmp(argv[1], "--crtc"))
196 id = get_crtc_fb(fd, id);
197 else if (!strcmp(argv[1], "--connector"))
198 id = get_connector_fb(fd, id);
199 else if (!strcmp(argv[1], "--plane"))
200 id = get_plane_fb(fd, id);
201 else if (strcmp(argv[1], "--fb"))
202 usage(argv[0], fd);
203
204 break;
205 case 2:
206 id = atoi(argv[1]);
207 if (id <= 0)
208 usage(argv[0], fd);
209
210 break;
211 default:
212 usage(argv[0], fd);
213 }
214
215 if (id <= 0) {
216 fprintf(stderr, "Failed to get framebuffer id\n");
217 return -1;
218 }
219
220 dump_fb(fd, id);
221
222 // /* Add delay */ }
223
224 return 0;
225 }
226