gallium: change remaining util functions to use cso sampler views
[mesa/mesa-lb.git] / progs / xdemos / glxsnoop.c
blob2e951345b5899dbdb58c556819adc152c570afc7
1 /**
2 * Display/snoop the z/stencil/back/front buffers of another app's window.
3 * Also, an example of the need for shared ancillary renderbuffers.
5 * Hint: use 'xwininfo' to get a window's ID.
7 * Brian Paul
8 * 11 Oct 2007
9 */
11 #define GL_GLEXT_PROTOTYPES
13 #include <GL/gl.h>
14 #include <GL/glx.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <X11/keysym.h>
21 #define Z_BUFFER 1
22 #define STENCIL_BUFFER 2
23 #define BACK_BUFFER 3
24 #define FRONT_BUFFER 4
27 static int Buffer = BACK_BUFFER;
28 static int WindowID = 0;
29 static const char *DisplayName = NULL;
30 static GLXContext Context = 0;
31 static int Width, Height;
34 /**
35 * Grab the z/stencil/back/front image from the srcWin and display it
36 * (possibly converted to grayscale) in the dstWin.
38 static void
39 redraw(Display *dpy, Window srcWin, Window dstWin )
41 GLubyte *image = malloc(Width * Height * 4);
43 glXMakeCurrent(dpy, srcWin, Context);
44 glPixelStorei(GL_PACK_ALIGNMENT, 1);
45 if (Buffer == BACK_BUFFER) {
46 glReadBuffer(GL_BACK);
47 glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, image);
49 else if (Buffer == FRONT_BUFFER) {
50 glReadBuffer(GL_FRONT);
51 glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, image);
53 else if (Buffer == Z_BUFFER) {
54 GLfloat *z = malloc(Width * Height * sizeof(GLfloat));
55 int i;
56 glReadPixels(0, 0, Width, Height, GL_DEPTH_COMPONENT, GL_FLOAT, z);
57 for (i = 0; i < Width * Height; i++) {
58 image[i*4+0] =
59 image[i*4+1] =
60 image[i*4+2] = (GLint) (255.0 * z[i]);
61 image[i*4+3] = 255;
63 free(z);
65 else if (Buffer == STENCIL_BUFFER) {
66 GLubyte *sten = malloc(Width * Height * sizeof(GLubyte));
67 int i, min = 100, max = -1;
68 float step;
69 int sz;
70 glGetIntegerv(GL_STENCIL_BITS, &sz);
71 glReadPixels(0, 0, Width, Height,
72 GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, sten);
73 /* find min/max for converting stencil to grayscale */
74 for (i = 0; i < Width * Height; i++) {
75 if (sten[i] < min)
76 min = sten[i];
77 if (sten[i] > max)
78 max = sten[i];
80 if (min == max)
81 step = 0;
82 else
83 step = 255.0 / (float) (max - min);
84 for (i = 0; i < Width * Height; i++) {
85 image[i*4+0] =
86 image[i*4+1] =
87 image[i*4+2] = (GLint) ((sten[i] - min) * step);
88 image[i*4+3] = 255;
90 free(sten);
93 glXMakeCurrent(dpy, dstWin, Context);
94 glWindowPos2iARB(0, 0);
95 glDrawBuffer(GL_FRONT);
96 glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, image);
97 glFlush();
99 free(image);
103 static void
104 set_window_title(Display *dpy, Window win, const char *title)
106 XSizeHints sizehints;
107 sizehints.flags = 0;
108 XSetStandardProperties(dpy, win, title, title,
109 None, (char **)NULL, 0, &sizehints);
113 static Window
114 make_gl_window(Display *dpy, XVisualInfo *visinfo, int width, int height)
116 int scrnum;
117 XSetWindowAttributes attr;
118 unsigned long mask;
119 Window root;
120 Window win;
121 int x = 0, y = 0;
122 char *name = NULL;
124 scrnum = DefaultScreen( dpy );
125 root = RootWindow( dpy, scrnum );
127 /* window attributes */
128 attr.background_pixel = 0;
129 attr.border_pixel = 0;
130 attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
131 attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
132 mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
134 win = XCreateWindow( dpy, root, x, y, width, height,
135 0, visinfo->depth, InputOutput,
136 visinfo->visual, mask, &attr );
138 /* set hints and properties */
140 XSizeHints sizehints;
141 sizehints.x = x;
142 sizehints.y = y;
143 sizehints.width = width;
144 sizehints.height = height;
145 sizehints.flags = USSize | USPosition;
146 XSetNormalHints(dpy, win, &sizehints);
147 XSetStandardProperties(dpy, win, name, name,
148 None, (char **)NULL, 0, &sizehints);
151 return win;
155 static void
156 update_window_title(Display *dpy, Window win)
158 char title[1000], *buf;
160 switch (Buffer) {
161 case Z_BUFFER:
162 buf = "Z";
163 break;
164 case STENCIL_BUFFER:
165 buf = "Stencil";
166 break;
167 case BACK_BUFFER:
168 buf = "Back";
169 break;
170 case FRONT_BUFFER:
171 buf = "Front";
172 break;
173 default:
174 buf = "";
177 sprintf(title, "glxsnoop window 0x%x (%s buffer)", (int) WindowID, buf);
179 set_window_title(dpy, win, title);
183 static void
184 keypress(Display *dpy, Window win, char key)
186 switch (key) {
187 case 27:
188 /* escape */
189 exit(0);
190 break;
191 case 's':
192 Buffer = STENCIL_BUFFER;
193 break;
194 case 'z':
195 Buffer = Z_BUFFER;
196 break;
197 case 'f':
198 Buffer = FRONT_BUFFER;
199 break;
200 case 'b':
201 Buffer = BACK_BUFFER;
202 break;
203 default:
204 return;
207 update_window_title(dpy, win);
208 redraw(dpy, WindowID, win);
212 static void
213 event_loop(Display *dpy, Window win)
215 XEvent event;
217 while (1) {
218 XNextEvent( dpy, &event );
220 switch (event.type) {
221 case Expose:
222 redraw(dpy, WindowID, win);
223 break;
224 case ConfigureNotify:
225 /*resize( event.xconfigure.width, event.xconfigure.height );*/
226 break;
227 case KeyPress:
229 char buffer[10];
230 int r, code;
231 code = XLookupKeysym(&event.xkey, 0);
232 if (code == XK_Left) {
234 else {
235 r = XLookupString(&event.xkey, buffer, sizeof(buffer),
236 NULL, NULL);
237 keypress(dpy, win, buffer[0]);
240 default:
241 /* nothing */
248 static VisualID
249 get_window_visualid(Display *dpy, Window win)
251 XWindowAttributes attr;
253 if (XGetWindowAttributes(dpy, win, &attr)) {
254 return attr.visual->visualid;
256 else {
257 return 0;
262 static void
263 get_window_size(Display *dpy, Window win, int *w, int *h)
265 XWindowAttributes attr;
267 if (XGetWindowAttributes(dpy, win, &attr)) {
268 *w = attr.width;
269 *h = attr.height;
271 else {
272 *w = *h = 0;
277 static XVisualInfo *
278 visualid_to_visualinfo(Display *dpy, VisualID vid)
280 XVisualInfo *vinfo, templ;
281 long mask;
282 int n;
284 templ.visualid = vid;
285 mask = VisualIDMask;
287 vinfo = XGetVisualInfo(dpy, mask, &templ, &n);
288 return vinfo;
292 static void
293 key_usage(void)
295 printf("Keyboard:\n");
296 printf(" z - display Z buffer\n");
297 printf(" s - display stencil buffer\n");
298 printf(" f - display front color buffer\n");
299 printf(" b - display back buffer\n");
303 static void
304 usage(void)
306 printf("Usage: glxsnoop [-display dpy] windowID\n");
307 key_usage();
311 static void
312 parse_opts(int argc, char *argv[])
314 int i;
316 for (i = 1; i < argc; i++) {
317 if (strcmp(argv[i], "-h") == 0) {
318 usage();
319 exit(0);
321 else if (strcmp(argv[i], "-display") == 0) {
322 DisplayName = argv[i + 1];
323 i++;
325 else {
326 if (argv[i][0] == '0' && argv[i][1] == 'x') {
327 /* hex */
328 WindowID = strtol(argv[i], NULL, 16);
330 else {
331 WindowID = atoi(argv[i]);
333 break;
337 if (!WindowID) {
338 usage();
339 exit(0);
345 main( int argc, char *argv[] )
347 Display *dpy;
348 VisualID vid;
349 XVisualInfo *visinfo;
350 Window win;
352 parse_opts(argc, argv);
354 key_usage();
356 dpy = XOpenDisplay(DisplayName);
358 /* find the VisualID for the named window */
359 vid = get_window_visualid(dpy, WindowID);
360 get_window_size(dpy, WindowID, &Width, &Height);
362 visinfo = visualid_to_visualinfo(dpy, vid);
364 Context = glXCreateContext( dpy, visinfo, NULL, True );
365 if (!Context) {
366 printf("Error: glXCreateContext failed\n");
367 exit(1);
370 win = make_gl_window(dpy, visinfo, Width, Height);
371 XMapWindow(dpy, win);
372 update_window_title(dpy, win);
374 event_loop( dpy, win );
376 return 0;