1 /* $Id: xdgagrab.c,v 1.3 1999/02/23 01:16:38 taoka Exp $ */
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <unistd.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <sys/mman.h>
9 #include <fcntl.h>
10 #include <X11/X.h>
11 #include <X11/Xlib.h>
12 #include <X11/extensions/xf86dga.h>
13
14 int
main(int argc,char * argv[])15 main(int argc, char *argv[])
16 {
17 Display *display;
18 Window root;
19 int fb_width, fb_height, vp_width, vp_height, x, y;
20 int fd, depth, bpp, screen, flags, banksize, fbufsize;
21 int nformats;
22 ScreenFormat *pixmap_format;
23 char *adrs, *ppmbuf;
24 char ppm_header[256];
25 uid_t uid = getuid(), euid = geteuid();
26 gid_t gid = getgid();
27 int fb_off = 0;
28
29 if(argc == 3){
30 fb_off = atoi(argv[2]);
31 }else if(argc != 2){
32 printf("usage: %s output_file [frame_buffer_offset]\n", argv[0]);
33 return 1;
34 }
35
36 display = XOpenDisplay(NULL);
37 if(display == NULL){
38 return 1;
39 }
40 screen = DefaultScreen(display);
41 root = DefaultRootWindow(display);
42 depth = DefaultDepth(display, screen);
43 nformats = ((_XPrivDisplay)display)->nformats;
44 pixmap_format = ((_XPrivDisplay)display)->pixmap_format;
45 while(nformats){
46 if(pixmap_format[nformats].depth == depth){
47 bpp = pixmap_format[nformats].bits_per_pixel;
48 break;
49 }
50 nformats--;
51 }
52 printf("depth is %d. bpp is %d.\n", depth, bpp);
53
54 XF86DGAQueryDirectVideo(display, screen, &flags);
55 if(flags & XF86DGADirectPresent){
56 printf("DGA capable\n");
57 }else{
58 XCloseDisplay(display);
59 return 1;
60 }
61
62 if(euid != 0){
63 printf("You are not a super user or %s is not set uid root .\n", argv[0]);
64 XCloseDisplay(display);
65 return 1;
66 }
67 // setuid(geteuid());
68
69 XF86DGAGetVideo(display, screen, &adrs, &fb_width, &banksize, &fbufsize);
70 if(banksize != fbufsize*1024){
71 printf("I cannot operate banked frame memory! Good-bye.\n");
72 XCloseDisplay(display);
73 return 1;
74 }
75 switch(bpp){
76 case 16:
77 fb_height = banksize/fb_width/2;
78 break;
79 case 24:
80 fb_height = banksize/fb_width/3;
81 break;
82 case 32:
83 fb_height = banksize/fb_width/4;
84 break;
85 default:
86 printf("depth must be 16, 24 or 32.\n");
87 XCloseDisplay(display);
88 return 1;
89 }
90 printf("frame buffer start: %p\n", (void *)adrs);
91 printf("frame buffer size: %d\n", (int)fbufsize);
92 printf("frame buffer dimension: %d x %d\n", fb_width, fb_height);
93
94 XF86DGAGetViewPortSize(display, screen, &vp_width, &vp_height);
95 printf("view port dimension: %d x %d\n", vp_width, vp_height);
96 XF86DGASetViewPort(display, screen, 0, 0);
97
98 sprintf(ppm_header, "P6\n%d %d\n255\n", vp_width, vp_height);
99 fd = open(argv[1], O_CREAT|O_TRUNC|O_RDWR, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
100 if(fd < 0){
101 printf("failed to open().\n");
102 XCloseDisplay(display);
103 return 1;
104 }
105 write(fd, ppm_header, strlen(ppm_header));
106 ppmbuf = malloc(vp_width*3);
107 if(ppmbuf == NULL){
108 printf("failed to malloc().\n");
109 close(fd);
110 XCloseDisplay(display);
111 return 1;
112 }
113 XF86DGADirectVideo(display, screen, XF86DGADirectGraphics);
114 switch(bpp){
115 case 16:
116 for(y = 0; y < vp_height; y++){
117 char *lb = adrs + (y*fb_width*2) + fb_off*2;
118 unsigned short pixel;
119 char *ppm = ppmbuf;
120
121 for(x = 0; x < vp_width; x++){
122 pixel = *((unsigned short *)(lb + (x*2)));
123 *ppm++ = (pixel & 0xF800) >> 8;
124 *ppm++ = (pixel & 0x07E0) >> 3;
125 *ppm++ = (pixel & 0x001F) << 3;
126 }
127 write(fd, ppmbuf, vp_width*3);
128 }
129 break;
130 case 24:
131 for(y = 0; y < vp_height; y++){
132 char *lb = adrs + (y*fb_width*3) + fb_off*3;
133 char *ppm = ppmbuf;
134
135 for(x = 0; x < vp_width; x++){
136 *ppm++ = *(lb + x*3 + 2);
137 *ppm++ = *(lb + x*3 + 1);
138 *ppm++ = *(lb + x*3 + 0);
139 }
140 write(fd, ppmbuf, vp_width*3);
141 }
142 break;
143 case 32:
144 for(y = 0; y < vp_height; y++){
145 char *lb = adrs + (y*fb_width*4) + fb_off*4;
146 char *ppm = ppmbuf;
147
148 for(x = 0; x < vp_width; x++){
149 *ppm++ = *(lb + x*4 + 2);
150 *ppm++ = *(lb + x*4 + 1);
151 *ppm++ = *(lb + x*4 + 0);
152 }
153 write(fd, ppmbuf, vp_width*3);
154 }
155 break;
156 }
157 XF86DGADirectVideo(display, screen, 0);
158 free(ppmbuf);
159 fchown(fd, uid, gid);
160 close(fd);
161 XCloseDisplay(display);
162 return 0;
163 }
164
165