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