Clone of mesa.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

glxsnoop.c 7.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  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.
  4. *
  5. * Hint: use 'xwininfo' to get a window's ID.
  6. *
  7. * Brian Paul
  8. * 11 Oct 2007
  9. */
  10. #define GL_GLEXT_PROTOTYPES
  11. #include <GL/gl.h>
  12. #include <GL/glx.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <X11/keysym.h>
  17. #define Z_BUFFER 1
  18. #define STENCIL_BUFFER 2
  19. #define BACK_BUFFER 3
  20. #define FRONT_BUFFER 4
  21. static int Buffer = BACK_BUFFER;
  22. static int WindowID = 0;
  23. static const char *DisplayName = NULL;
  24. static GLXContext Context = 0;
  25. static int Width, Height;
  26. /**
  27. * Grab the z/stencil/back/front image from the srcWin and display it
  28. * (possibly converted to grayscale) in the dstWin.
  29. */
  30. static void
  31. redraw(Display *dpy, Window srcWin, Window dstWin )
  32. {
  33. GLubyte *image = malloc(Width * Height * 4);
  34. glXMakeCurrent(dpy, srcWin, Context);
  35. glPixelStorei(GL_PACK_ALIGNMENT, 1);
  36. if (Buffer == BACK_BUFFER) {
  37. glReadBuffer(GL_BACK);
  38. glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, image);
  39. }
  40. else if (Buffer == FRONT_BUFFER) {
  41. glReadBuffer(GL_FRONT);
  42. glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, image);
  43. }
  44. else if (Buffer == Z_BUFFER) {
  45. GLfloat *z = malloc(Width * Height * sizeof(GLfloat));
  46. int i;
  47. glReadPixels(0, 0, Width, Height, GL_DEPTH_COMPONENT, GL_FLOAT, z);
  48. for (i = 0; i < Width * Height; i++) {
  49. image[i*4+0] =
  50. image[i*4+1] =
  51. image[i*4+2] = (GLint) (255.0 * z[i]);
  52. image[i*4+3] = 255;
  53. }
  54. free(z);
  55. }
  56. else if (Buffer == STENCIL_BUFFER) {
  57. GLubyte *sten = malloc(Width * Height * sizeof(GLubyte));
  58. int i, min = 100, max = -1;
  59. float step;
  60. int sz;
  61. glGetIntegerv(GL_STENCIL_BITS, &sz);
  62. glReadPixels(0, 0, Width, Height,
  63. GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, sten);
  64. /* find min/max for converting stencil to grayscale */
  65. for (i = 0; i < Width * Height; i++) {
  66. if (sten[i] < min)
  67. min = sten[i];
  68. if (sten[i] > max)
  69. max = sten[i];
  70. }
  71. if (min == max)
  72. step = 0;
  73. else
  74. step = 255.0 / (float) (max - min);
  75. for (i = 0; i < Width * Height; i++) {
  76. image[i*4+0] =
  77. image[i*4+1] =
  78. image[i*4+2] = (GLint) ((sten[i] - min) * step);
  79. image[i*4+3] = 255;
  80. }
  81. free(sten);
  82. }
  83. glXMakeCurrent(dpy, dstWin, Context);
  84. glWindowPos2iARB(0, 0);
  85. glDrawBuffer(GL_FRONT);
  86. glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, image);
  87. glFlush();
  88. free(image);
  89. }
  90. static void
  91. set_window_title(Display *dpy, Window win, const char *title)
  92. {
  93. XSizeHints sizehints;
  94. sizehints.flags = 0;
  95. XSetStandardProperties(dpy, win, title, title,
  96. None, (char **)NULL, 0, &sizehints);
  97. }
  98. static Window
  99. make_gl_window(Display *dpy, XVisualInfo *visinfo, int width, int height)
  100. {
  101. int scrnum;
  102. XSetWindowAttributes attr;
  103. unsigned long mask;
  104. Window root;
  105. Window win;
  106. int x = 0, y = 0;
  107. char *name = NULL;
  108. scrnum = DefaultScreen( dpy );
  109. root = RootWindow( dpy, scrnum );
  110. /* window attributes */
  111. attr.background_pixel = 0;
  112. attr.border_pixel = 0;
  113. attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
  114. attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
  115. mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
  116. win = XCreateWindow( dpy, root, x, y, width, height,
  117. 0, visinfo->depth, InputOutput,
  118. visinfo->visual, mask, &attr );
  119. /* set hints and properties */
  120. {
  121. XSizeHints sizehints;
  122. sizehints.x = x;
  123. sizehints.y = y;
  124. sizehints.width = width;
  125. sizehints.height = height;
  126. sizehints.flags = USSize | USPosition;
  127. XSetNormalHints(dpy, win, &sizehints);
  128. XSetStandardProperties(dpy, win, name, name,
  129. None, (char **)NULL, 0, &sizehints);
  130. }
  131. return win;
  132. }
  133. static void
  134. update_window_title(Display *dpy, Window win)
  135. {
  136. char title[1000], *buf;
  137. switch (Buffer) {
  138. case Z_BUFFER:
  139. buf = "Z";
  140. break;
  141. case STENCIL_BUFFER:
  142. buf = "Stencil";
  143. break;
  144. case BACK_BUFFER:
  145. buf = "Back";
  146. break;
  147. case FRONT_BUFFER:
  148. buf = "Front";
  149. break;
  150. default:
  151. buf = "";
  152. }
  153. sprintf(title, "glxsnoop window 0x%x (%s buffer)", (int) WindowID, buf);
  154. set_window_title(dpy, win, title);
  155. }
  156. static void
  157. keypress(Display *dpy, Window win, char key)
  158. {
  159. switch (key) {
  160. case 27:
  161. /* escape */
  162. exit(0);
  163. break;
  164. case 's':
  165. Buffer = STENCIL_BUFFER;
  166. break;
  167. case 'z':
  168. Buffer = Z_BUFFER;
  169. break;
  170. case 'f':
  171. Buffer = FRONT_BUFFER;
  172. break;
  173. case 'b':
  174. Buffer = BACK_BUFFER;
  175. break;
  176. default:
  177. return;
  178. }
  179. update_window_title(dpy, win);
  180. redraw(dpy, WindowID, win);
  181. }
  182. static void
  183. event_loop(Display *dpy, Window win)
  184. {
  185. XEvent event;
  186. while (1) {
  187. XNextEvent( dpy, &event );
  188. switch (event.type) {
  189. case Expose:
  190. redraw(dpy, WindowID, win);
  191. break;
  192. case ConfigureNotify:
  193. /*resize( event.xconfigure.width, event.xconfigure.height );*/
  194. break;
  195. case KeyPress:
  196. {
  197. char buffer[10];
  198. int r, code;
  199. code = XLookupKeysym(&event.xkey, 0);
  200. if (code == XK_Left) {
  201. }
  202. else {
  203. r = XLookupString(&event.xkey, buffer, sizeof(buffer),
  204. NULL, NULL);
  205. keypress(dpy, win, buffer[0]);
  206. }
  207. }
  208. default:
  209. /* nothing */
  210. ;
  211. }
  212. }
  213. }
  214. static VisualID
  215. get_window_visualid(Display *dpy, Window win)
  216. {
  217. XWindowAttributes attr;
  218. if (XGetWindowAttributes(dpy, win, &attr)) {
  219. return attr.visual->visualid;
  220. }
  221. else {
  222. return 0;
  223. }
  224. }
  225. static void
  226. get_window_size(Display *dpy, Window win, int *w, int *h)
  227. {
  228. XWindowAttributes attr;
  229. if (XGetWindowAttributes(dpy, win, &attr)) {
  230. *w = attr.width;
  231. *h = attr.height;
  232. }
  233. else {
  234. *w = *h = 0;
  235. }
  236. }
  237. static XVisualInfo *
  238. visualid_to_visualinfo(Display *dpy, VisualID vid)
  239. {
  240. XVisualInfo *vinfo, templ;
  241. long mask;
  242. int n;
  243. templ.visualid = vid;
  244. mask = VisualIDMask;
  245. vinfo = XGetVisualInfo(dpy, mask, &templ, &n);
  246. return vinfo;
  247. }
  248. static void
  249. key_usage(void)
  250. {
  251. printf("Keyboard:\n");
  252. printf(" z - display Z buffer\n");
  253. printf(" s - display stencil buffer\n");
  254. printf(" f - display front color buffer\n");
  255. printf(" b - display back buffer\n");
  256. }
  257. static void
  258. usage(void)
  259. {
  260. printf("Usage: glxsnoop [-display dpy] windowID\n");
  261. key_usage();
  262. }
  263. static void
  264. parse_opts(int argc, char *argv[])
  265. {
  266. int i;
  267. for (i = 1; i < argc; i++) {
  268. if (strcmp(argv[i], "-h") == 0) {
  269. usage();
  270. exit(0);
  271. }
  272. else if (strcmp(argv[i], "-display") == 0) {
  273. DisplayName = argv[i + 1];
  274. i++;
  275. }
  276. else {
  277. if (argv[i][0] == '0' && argv[i][1] == 'x') {
  278. /* hex */
  279. WindowID = strtol(argv[i], NULL, 16);
  280. }
  281. else {
  282. WindowID = atoi(argv[i]);
  283. }
  284. break;
  285. }
  286. }
  287. if (!WindowID) {
  288. usage();
  289. exit(0);
  290. }
  291. }
  292. int
  293. main( int argc, char *argv[] )
  294. {
  295. Display *dpy;
  296. VisualID vid;
  297. XVisualInfo *visinfo;
  298. Window win;
  299. parse_opts(argc, argv);
  300. key_usage();
  301. dpy = XOpenDisplay(DisplayName);
  302. /* find the VisualID for the named window */
  303. vid = get_window_visualid(dpy, WindowID);
  304. get_window_size(dpy, WindowID, &Width, &Height);
  305. visinfo = visualid_to_visualinfo(dpy, vid);
  306. Context = glXCreateContext( dpy, visinfo, NULL, True );
  307. if (!Context) {
  308. printf("Error: glXCreateContext failed\n");
  309. exit(1);
  310. }
  311. win = make_gl_window(dpy, visinfo, Width, Height);
  312. XMapWindow(dpy, win);
  313. update_window_title(dpy, win);
  314. event_loop( dpy, win );
  315. return 0;
  316. }