diff options
Diffstat (limited to 'progs/xdemos')
| -rw-r--r-- | progs/xdemos/.gitignore | 4 | ||||
| -rw-r--r-- | progs/xdemos/Makefile | 60 | ||||
| -rw-r--r-- | progs/xdemos/corender.c | 400 | ||||
| -rw-r--r-- | progs/xdemos/glsync.c | 273 | ||||
| -rw-r--r-- | progs/xdemos/glxgears.c | 52 | ||||
| -rw-r--r-- | progs/xdemos/glxgears_pixmap.c | 547 | ||||
| -rw-r--r-- | progs/xdemos/glxinfo.c | 293 | ||||
| -rw-r--r-- | progs/xdemos/glxsnoop.c | 377 | ||||
| -rw-r--r-- | progs/xdemos/glxswapcontrol.c | 94 | ||||
| -rw-r--r-- | progs/xdemos/ipc.c | 264 | ||||
| -rw-r--r-- | progs/xdemos/ipc.h | 16 | ||||
| -rw-r--r-- | progs/xdemos/offset.c | 3 | ||||
| -rw-r--r-- | progs/xdemos/pbutil.c | 72 | ||||
| -rw-r--r-- | progs/xdemos/pbutil.h | 3 | ||||
| -rw-r--r-- | progs/xdemos/shape.c | 1 | 
15 files changed, 2354 insertions, 105 deletions
| diff --git a/progs/xdemos/.gitignore b/progs/xdemos/.gitignore index 34551101cb..084dee5d84 100644 --- a/progs/xdemos/.gitignore +++ b/progs/xdemos/.gitignore @@ -1,12 +1,16 @@ +corender +glsync  glthreads  glxcontexts  glxdemo  glxgears  glxgears_fbconfig +glxgears_pixmap  glxheads  glxinfo  glxpbdemo  glxpixmap +glxsnoop  glxswapcontrol  manywin  offset diff --git a/progs/xdemos/Makefile b/progs/xdemos/Makefile index 38f3884d58..8d248fb0a9 100644 --- a/progs/xdemos/Makefile +++ b/progs/xdemos/Makefile @@ -6,17 +6,24 @@ include $(TOP)/configs/current  INCDIR = $(TOP)/include -LIB_DEP = $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME) $(TOP)/$(LIB_DIR)/$(GLU_LIB_NAME) +LIB_DEP = $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME) -PROGS = glthreads \ +LIBS = -L$(TOP)/$(LIB_DIR) -l$(GL_LIB) $(APP_LIB_DEPS) + +PROGS = \ +	corender \ +	glsync \ +	glthreads \  	glxdemo \  	glxgears \  	glxgears_fbconfig \ +	glxgears_pixmap \  	glxcontexts \  	glxheads \  	glxinfo \  	glxpixmap \  	glxpbdemo \ +	glxsnoop \  	glxswapcontrol \  	manywin \  	offset \ @@ -27,10 +34,14 @@ PROGS = glthreads \  	texture_from_pixmap \  	wincopy \  	xfont \ -	xrotfontdemo \ -	yuvrect_client +	xrotfontdemo + +# Don't build these by default because of extra library dependencies +EXTRA_PROGS = \ +	shape \ +	yuvrect_client \ +	xdemo -# omit this XMesa API demo:	xdemo  ##### RULES ##### @@ -39,7 +50,7 @@ PROGS = glthreads \  .SUFFIXES: .c  .c: $(LIB_DEP) -	$(APP_CC) -I$(INCDIR) $(CFLAGS) $< $(APP_LIB_DEPS) -o $@ +	$(APP_CC) -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) $(LDFLAGS) $< $(LIBS) -o $@  ##### TARGETS ##### @@ -47,39 +58,54 @@ PROGS = glthreads \  default: $(PROGS) +extra: $(EXTRA_PROGS) + +  clean: -	-rm -f $(PROGS) +	-rm -f $(PROGS) $(EXTRA_PROGS)  	-rm -f *.o *~  # special cases  pbinfo: pbinfo.o pbutil.o -	$(APP_CC) -I$(INCDIR) $(CFLAGS) pbinfo.o pbutil.o $(APP_LIB_DEPS) -o $@ +	$(APP_CC) $(CFLAGS) $(LDFLAGS) pbinfo.o pbutil.o $(LIBS) -o $@  pbdemo: pbdemo.o pbutil.o -	$(APP_CC) -I$(INCDIR) $(CFLAGS) pbdemo.o pbutil.o $(APP_LIB_DEPS) -o $@ +	$(APP_CC) $(CFLAGS) $(LDFLAGS) pbdemo.o pbutil.o $(LIBS) -o $@  pbinfo.o: pbinfo.c pbutil.h -	$(APP_CC) -c -I. -I$(INCDIR) $(CFLAGS) pbinfo.c +	$(APP_CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) pbinfo.c  pbdemo.o: pbdemo.c pbutil.h -	$(APP_CC) -c -I. -I$(INCDIR) $(CFLAGS) pbdemo.c +	$(APP_CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) pbdemo.c  pbutil.o: pbutil.c pbutil.h -	$(APP_CC) -c -I. -I$(INCDIR) $(CFLAGS) pbutil.c +	$(APP_CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) pbutil.c  glxgears_fbconfig: glxgears_fbconfig.o pbutil.o -	$(APP_CC) -I$(INCDIR) $(CFLAGS) glxgears_fbconfig.o pbutil.o $(APP_LIB_DEPS) -o $@ +	$(APP_CC) $(CFLAGS) $(LDFLAGS) glxgears_fbconfig.o pbutil.o $(LIBS) -o $@  glxgears_fbconfig.o: glxgears_fbconfig.c pbutil.h -	$(APP_CC) -I$(INCDIR) $(CFLAGS) -c -I. $(CFLAGS) glxgears_fbconfig.c +	$(APP_CC) -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) -c -I. $(CFLAGS) glxgears_fbconfig.c  xrotfontdemo: xrotfontdemo.o xuserotfont.o -	$(APP_CC) -I$(INCDIR) $(CFLAGS) xrotfontdemo.o xuserotfont.o $(APP_LIB_DEPS) -o $@ +	$(APP_CC) $(CFLAGS) $(LDFLAGS) xrotfontdemo.o xuserotfont.o $(LIBS) -o $@  xuserotfont.o: xuserotfont.c xuserotfont.h -	$(APP_CC) -c -I. -I$(INCDIR) $(CFLAGS) xuserotfont.c +	$(APP_CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) xuserotfont.c  xrotfontdemo.o: xrotfontdemo.c xuserotfont.h -	$(APP_CC) -c -I. -I$(INCDIR) $(CFLAGS) xrotfontdemo.c +	$(APP_CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) xrotfontdemo.c + +corender: corender.o ipc.o +	$(APP_CC) $(CFLAGS) corender.o ipc.o $(LIBS) -o $@ + +corender.o: corender.c ipc.h +	$(APP_CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) corender.c + +ipc.o: ipc.c ipc.h +	$(APP_CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) ipc.c + +yuvrect_client: yuvrect_client.c +	$(APP_CC) -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) $< $(LDFLAGS) $(LIBS) -l$(GLU_LIB) -o $@ diff --git a/progs/xdemos/corender.c b/progs/xdemos/corender.c new file mode 100644 index 0000000000..f2b8145e52 --- /dev/null +++ b/progs/xdemos/corender.c @@ -0,0 +1,400 @@ +/** + * Example of cooperative rendering into one window by two processes. + * The first instance of the program creates the GLX window. + * The second instance of the program gets the window ID from the first + * and draws into it. + * Socket IPC is used for synchronization. + * + * Usage: + * 1. run 'corender &' + * 2. run 'corender 2'  (any arg will do) + * + * Brian Paul + * 11 Oct 2007 + */ + + +#include <GL/gl.h> +#include <GL/glx.h> +#include <assert.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <X11/keysym.h> +#include <unistd.h> +#include "ipc.h" + + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +static int MyID = 0;  /* 0 or 1 */ +static int WindowID = 0; +static GLXContext Context = 0; +static int Width = 700, Height = 350; +static int Rot = 0; +static int Sock = 0; + +static GLfloat Red[4] = {1.0, 0.2, 0.2, 1.0}; +static GLfloat Blue[4] = {0.2, 0.2, 1.0, 1.0}; + +static int Sync = 1;  /** synchronized rendering? */ + + +static void +setup_ipc(void) +{ +   int k, port = 10001; + +   if (MyID == 0) { +      /* I'm the first one, wait for connection from second */ +      k = CreatePort(&port); +      assert(k != -1); + +      printf("Waiting for connection from another 'corender'\n"); +      Sock = AcceptConnection(k); + +      printf("Got connection, sending windowID\n"); + +      /* send windowID */ +      SendData(Sock, &WindowID, sizeof(WindowID)); +   } +   else { +      /* I'm the second one, connect to first */ +      char hostname[1000]; + +      MyHostName(hostname, 1000); +      Sock = Connect(hostname, port); +      assert(Sock != -1); + +      /* get windowID */ +      ReceiveData(Sock, &WindowID, sizeof(WindowID)); +      printf("Contacted first 'corender', getting WindowID\n"); +   } +} + + + +/** from GLUT */ +static void +doughnut(GLfloat r, GLfloat R, GLint nsides, GLint rings) +{ +  int i, j; +  GLfloat theta, phi, theta1; +  GLfloat cosTheta, sinTheta; +  GLfloat cosTheta1, sinTheta1; +  GLfloat ringDelta, sideDelta; + +  ringDelta = 2.0 * M_PI / rings; +  sideDelta = 2.0 * M_PI / nsides; + +  theta = 0.0; +  cosTheta = 1.0; +  sinTheta = 0.0; +  for (i = rings - 1; i >= 0; i--) { +    theta1 = theta + ringDelta; +    cosTheta1 = cos(theta1); +    sinTheta1 = sin(theta1); +    glBegin(GL_QUAD_STRIP); +    phi = 0.0; +    for (j = nsides; j >= 0; j--) { +      GLfloat cosPhi, sinPhi, dist; + +      phi += sideDelta; +      cosPhi = cos(phi); +      sinPhi = sin(phi); +      dist = R + r * cosPhi; + +      glNormal3f(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi); +      glVertex3f(cosTheta1 * dist, -sinTheta1 * dist, r * sinPhi); +      glNormal3f(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi); +      glVertex3f(cosTheta * dist, -sinTheta * dist,  r * sinPhi); +    } +    glEnd(); +    theta = theta1; +    cosTheta = cosTheta1; +    sinTheta = sinTheta1; +  } +} + + +static void +redraw(Display *dpy) +{ +   int dbg = 0; + +   glXMakeCurrent(dpy, WindowID, Context); +   glEnable(GL_LIGHTING); +   glEnable(GL_LIGHT0); +   glEnable(GL_DEPTH_TEST); +   glClearColor(0.5, 0.5, 0.5, 0.0); + +   if (MyID == 0) { +      /* First process */ + +      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + +      glPushMatrix(); +      glTranslatef(-1, 0, 0); +      glRotatef(Rot, 1, 0, 0); +      glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Red); +      doughnut(0.5, 2.0, 20, 30); +      glPopMatrix(); + +      glFinish(); +      if (!Sync) { +         usleep(1000*10); +      } + +      /* signal second process to render */ +      if (Sync) { +         int code = 1; +         if (dbg) printf("0: send signal\n"); +         SendData(Sock, &code, sizeof(code)); +         SendData(Sock, &Rot, sizeof(Rot)); +      } + +      /* wait for second process to finish rendering */ +      if (Sync) { +         int code = 0; +         if (dbg) printf("0: wait signal\n"); +         ReceiveData(Sock, &code, sizeof(code)); +         if (dbg) printf("0: got signal\n"); +         assert(code == 2); +      } + +   } +   else { +      /* Second process */ + +      /* wait for first process's signal for me to render */ +      if (Sync) { +         int code = 0; +         if (dbg) printf("1: wait signal\n"); +         ReceiveData(Sock, &code, sizeof(code)); +         ReceiveData(Sock, &Rot, sizeof(Rot)); + +         if (dbg) printf("1: got signal\n"); +         assert(code == 1); +      } + +      /* XXX this clear should not be here, but for some reason, it +       * makes things _mostly_ work correctly w/ NVIDIA's driver. +       * There's only occasional glitches. +       * Without this glClear(), depth buffer for the second process +       * is pretty much broken. +       */ +      //glClear(GL_DEPTH_BUFFER_BIT); + +      glPushMatrix(); +      glTranslatef(1, 0, 0); +      glRotatef(Rot + 90 , 1, 0, 0); +      glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Blue); +      doughnut(0.5, 2.0, 20, 30); +      glPopMatrix(); +      glFinish(); + +      glXSwapBuffers(dpy, WindowID); +      usleep(1000*10); + +      /* signal first process that I'm done rendering */ +      if (Sync) { +         int code = 2; +         if (dbg) printf("1: send signal\n"); +         SendData(Sock, &code, sizeof(code)); +      } +   } +} + + +static void +resize(Display *dpy, int width, int height) +{ +   float ar = (float) width / height; + +   glXMakeCurrent(dpy, WindowID, Context); + +   glViewport(0, 0, width, height); +   glMatrixMode(GL_PROJECTION); +   glLoadIdentity(); +   glFrustum(-ar, ar, 1.0, -1.0, 5.0, 200.0); +   glMatrixMode(GL_MODELVIEW); +   glLoadIdentity(); +   glTranslatef(0, 0, -15); + +   Width = width; +   Height = height; +} + + + +static void +set_window_title(Display *dpy, Window win, const char *title) +{ +   XSizeHints sizehints; +   sizehints.flags = 0; +   XSetStandardProperties(dpy, win, title, title, +                          None, (char **)NULL, 0, &sizehints); +} + + +static Window +make_gl_window(Display *dpy, XVisualInfo *visinfo, int width, int height) +{ +   int scrnum; +   XSetWindowAttributes attr; +   unsigned long mask; +   Window root; +   Window win; +   int x = 0, y = 0; +   char *name = NULL; + +   scrnum = DefaultScreen( dpy ); +   root = RootWindow( dpy, scrnum ); + +   /* window attributes */ +   attr.background_pixel = 0; +   attr.border_pixel = 0; +   attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone); +   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; +   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; + +   win = XCreateWindow( dpy, root, x, y, width, height, +		        0, visinfo->depth, InputOutput, +		        visinfo->visual, mask, &attr ); + +   /* set hints and properties */ +   { +      XSizeHints sizehints; +      sizehints.x = x; +      sizehints.y = y; +      sizehints.width  = width; +      sizehints.height = height; +      sizehints.flags = USSize | USPosition; +      XSetNormalHints(dpy, win, &sizehints); +      XSetStandardProperties(dpy, win, name, name, +                              None, (char **)NULL, 0, &sizehints); +   } + +   return win; +} + + +static void +set_event_mask(Display *dpy, Window win) +{ +   XSetWindowAttributes attr; +   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; +   XChangeWindowAttributes(dpy, win, CWEventMask, &attr); +} + + +static void +event_loop(Display *dpy) +{ +   while (1) { +      while (XPending(dpy) > 0) { +         XEvent event; +         XNextEvent(dpy, &event); + +         switch (event.type) { +         case Expose: +            redraw(dpy); +            break; +         case ConfigureNotify: +            resize(dpy, event.xconfigure.width, event.xconfigure.height); +            break; +         case KeyPress: +            { +               char buffer[10]; +               int r, code; +               code = XLookupKeysym(&event.xkey, 0); +               if (code == XK_Left) { +               } +               else { +                  r = XLookupString(&event.xkey, buffer, sizeof(buffer), +                                    NULL, NULL); +                  if (buffer[0] == 27) { +                     exit(0); +                  } +               } +            } +         default: +            /* nothing */ +            ; +         } +      } + +      if (MyID == 0 || !Sync) +         Rot += 1; +      redraw(dpy); +   } +} + + +static XVisualInfo * +choose_visual(Display *dpy) +{ +   int attribs[] = { GLX_RGBA, +                     GLX_RED_SIZE, 1, +                     GLX_GREEN_SIZE, 1, +                     GLX_BLUE_SIZE, 1, +                     GLX_DOUBLEBUFFER, +                     GLX_DEPTH_SIZE, 1, +                     None }; +   int scrnum = DefaultScreen( dpy ); +   return glXChooseVisual(dpy, scrnum, attribs); +} + + +static void +parse_opts(int argc, char *argv[]) +{ +   if (argc > 1) { +      MyID = 1; +   } +} + + +int +main( int argc, char *argv[] ) +{ +   Display *dpy; +   XVisualInfo *visinfo; + +   parse_opts(argc, argv); + +   dpy = XOpenDisplay(NULL); + +   visinfo = choose_visual(dpy); + +   Context = glXCreateContext( dpy, visinfo, NULL, True ); +   if (!Context) { +      printf("Error: glXCreateContext failed\n"); +      exit(1); +   } + +   if (MyID == 0) { +      WindowID = make_gl_window(dpy, visinfo, Width, Height); +      set_window_title(dpy, WindowID, "corender"); +      XMapWindow(dpy, WindowID); +      /*printf("WindowID 0x%x\n", (int) WindowID);*/ +   } + +   /* do ipc hand-shake here */ +   setup_ipc(); +   assert(Sock); +   assert(WindowID); + +   if (MyID == 1) { +      set_event_mask(dpy, WindowID); +   } + +   resize(dpy, Width, Height); + +   event_loop(dpy); + +   return 0; +} diff --git a/progs/xdemos/glsync.c b/progs/xdemos/glsync.c new file mode 100644 index 0000000000..95cd1af400 --- /dev/null +++ b/progs/xdemos/glsync.c @@ -0,0 +1,273 @@ +/* + * Copyright © 2007 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + *    Jesse Barnes <jesse.barnes@intel.com> + * + */ + +/** @file glsync.c + * The program is simple:  it paints a window alternating colors (red & + * white) either as fast as possible or synchronized to vblank events + * + * If run normally, the program should display a window that exhibits + * significant tearing between red and white colors (e.g. you might get + * a "waterfall" effect of red and white horizontal bars). + * + * If run with the '-s b' option, the program should synchronize the + * window color changes with the vertical blank period, resulting in a + * window that looks orangish with a high frequency flicker (which may + * be invisible).  If the window is moved to another screen, this + * property should be preserved.  If the window spans two screens, it + * shouldn't tear on whichever screen most of the window is on; the + * portion on the other screen may show some tearing (like the + * waterfall effect above). + * + * Other options include '-w <width>' and '-h <height' to set the + * window size. + */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <GL/gl.h> +#include <GL/glu.h> +#include <GL/glx.h> +#include <GL/glxext.h> +#include <X11/X.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> + +void (*video_sync_get)(); +void (*video_sync)(); + +static int GLXExtensionSupported(Display *dpy, const char *extension) +{ +	const char *extensionsString, *client_extensions, *pos; + +	extensionsString = glXQueryExtensionsString(dpy, DefaultScreen(dpy)); +	client_extensions = glXGetClientString(dpy, GLX_EXTENSIONS); + +	pos = strstr(extensionsString, extension); + +	if (pos != NULL && (pos == extensionsString || pos[-1] == ' ') && +	    (pos[strlen(extension)] == ' ' || pos[strlen(extension)] == '\0')) +		return 1; + +	pos = strstr(client_extensions, extension); + +	if (pos != NULL && (pos == extensionsString || pos[-1] == ' ') && +	    (pos[strlen(extension)] == ' ' || pos[strlen(extension)] == '\0')) +		return 1; + +	return 0; +} + +extern char *optarg; +extern int optind, opterr, optopt; +static char optstr[] = "w:h:s:v"; + +enum sync_type { +	none = 0, +	sgi_video_sync, +	buffer_swap, +}; + +static void usage(char *name) +{ +	printf("usage: %s [-w <width>] [-h <height>] [-s<sync method>] " +	       "[-vc]\n", name); +	printf("\t-s<sync method>:\n"); +	printf("\t\tn: none\n"); +	printf("\t\ts: SGI video sync extension\n"); +	printf("\t\tb: buffer swap\n"); +	printf("\t-v: verbose (print count)\n"); +	exit(-1); +} + +int main(int argc, char *argv[]) +{ +	Display *disp; +	XVisualInfo *pvi; +	XSetWindowAttributes swa; +	int attrib[14]; +	GLint last_val = -1, count = 0; +	Window winGL; +	int dummy; +	Atom wmDelete; +	enum sync_type waitforsync = none; +	int width = 500, height = 500, verbose = 0, +		countonly = 0; +	int c, i = 1; + +	opterr = 0; +	while ((c = getopt(argc, argv, optstr)) != -1) { +		switch (c) { +		case 'w': +			width = atoi(optarg); +			break; +		case 'h': +			height = atoi(optarg); +			break; +		case 's': +			switch (optarg[0]) { +			case 'n': +				waitforsync = none; +				break; +			case 's': +				waitforsync = sgi_video_sync; +				break; +			case 'b': +				waitforsync = buffer_swap; +				break; +			default: +				usage(argv[0]); +				break; +			} +			break; +		case 'v': +			verbose = 1; +			break; +		default: +			usage(argv[0]); +			break; +		} +	} + +	disp = XOpenDisplay(NULL); +	if (!disp) { +		fprintf(stderr, "failed to open display\n"); +		return -1; +	} + +	if (!glXQueryExtension(disp, &dummy, &dummy)) { +		fprintf(stderr, "glXQueryExtension failed\n"); +		return -1; +	} + +	if (!GLXExtensionSupported(disp, "GLX_SGI_video_sync")) { +		fprintf(stderr, "GLX_SGI_video_sync not supported, exiting\n"); +		return -1; +	} + +	attrib[0] = GLX_RGBA; +	attrib[1] = 1; +	attrib[2] = GLX_RED_SIZE; +	attrib[3] = 1; +	attrib[4] = GLX_GREEN_SIZE; +	attrib[5] = 1; +	attrib[6] = GLX_BLUE_SIZE; +	attrib[7] = 1; +	if (waitforsync != buffer_swap) +		attrib[8] = None; +	else { +		attrib[8] = GLX_DOUBLEBUFFER; +		attrib[9] = 1; +		attrib[10] = None; +	} + +	GLXContext context; +	pvi = glXChooseVisual(disp, DefaultScreen(disp), attrib); +	if (!pvi) { +		fprintf(stderr, "failed to choose visual, exiting\n"); +		return -1; +	} + +	context = glXCreateContext(disp, pvi, None, GL_TRUE); +	if (!context) { +		fprintf(stderr, "failed to create glx context\n"); +		return -1; +	} + +	pvi->screen = DefaultScreen(disp); + +	swa.colormap = XCreateColormap(disp, RootWindow(disp, pvi->screen), +				       pvi->visual, AllocNone); +	swa.border_pixel = 0; +	swa.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | +		StructureNotifyMask; +	winGL = XCreateWindow(disp, RootWindow(disp, pvi->screen), +			      0, 0, +			      width, height, +			      0, pvi->depth, InputOutput, pvi->visual, +			      CWBorderPixel | CWColormap | CWEventMask, &swa); +	if (!winGL) { +		fprintf(stderr, "window creation failed\n"); +		return -1; +	} +        wmDelete = XInternAtom(disp, "WM_DELETE_WINDOW", True); +        XSetWMProtocols(disp, winGL, &wmDelete, 1); + +	XSetStandardProperties(disp, winGL, "glsync test", "glsync text", +			       None, NULL, 0, NULL); + +	XMapRaised(disp, winGL); + +	glXMakeCurrent(disp, winGL, context); + +	video_sync_get = glXGetProcAddress((unsigned char *)"glXGetVideoSyncSGI"); +	video_sync = glXGetProcAddress((unsigned char *)"glXWaitVideoSyncSGI"); + +	if (!video_sync_get || !video_sync) { +		fprintf(stderr, "failed to get sync functions\n"); +		return -1; +	} + +	video_sync_get(&count); +	count++; +	while (i++) { +		/* Wait for vsync */ +		if (waitforsync == sgi_video_sync) { +			if (verbose) +				fprintf(stderr, "waiting on count %d\n", count); +			video_sync(2, (count + 1) % 2, &count); +			if (count < last_val) +				fprintf(stderr, "error:  vblank count went backwards: %d -> %d\n", last_val, count); +			if (count == last_val) +				fprintf(stderr, "error:  count didn't change: %d\n", count); +			last_val = count; +		} else if (waitforsync == buffer_swap) { +			glXSwapBuffers(disp, winGL); +		} + +		if (countonly) { +			video_sync(2, 1, &count); +			fprintf(stderr, "current count: %d\n", count); +			sleep(1); +			continue; +		} + +		/* Alternate colors to make tearing obvious */ +		if (i & 1) +			glClearColor(1.0f, 1.0f, 1.0f, 1.0f); +		else +			glClearColor(1.0f, 0.0f, 0.0f, 0.0f); +		glClear(GL_COLOR_BUFFER_BIT); +		glFlush(); +	} + +	XDestroyWindow(disp, winGL); +	glXDestroyContext(disp, context); +	XCloseDisplay(disp); + +	return 0; +} diff --git a/progs/xdemos/glxgears.c b/progs/xdemos/glxgears.c index c98c3157b5..8db717f1aa 100644 --- a/progs/xdemos/glxgears.c +++ b/progs/xdemos/glxgears.c @@ -419,6 +419,52 @@ init(void)  } +/** + * Remove window border/decorations. + */ +static void +no_border( Display *dpy, Window w) +{ +   static const unsigned MWM_HINTS_DECORATIONS = (1 << 1); +   static const int PROP_MOTIF_WM_HINTS_ELEMENTS = 5; + +   typedef struct +   { +      unsigned long       flags; +      unsigned long       functions; +      unsigned long       decorations; +      long                inputMode; +      unsigned long       status; +   } PropMotifWmHints; + +   PropMotifWmHints motif_hints; +   Atom prop, proptype; +   unsigned long flags = 0; + +   /* setup the property */ +   motif_hints.flags = MWM_HINTS_DECORATIONS; +   motif_hints.decorations = flags; + +   /* get the atom for the property */ +   prop = XInternAtom( dpy, "_MOTIF_WM_HINTS", True ); +   if (!prop) { +      /* something went wrong! */ +      return; +   } + +   /* not sure this is correct, seems to work, XA_WM_HINTS didn't work */ +   proptype = prop; + +   XChangeProperty( dpy, w,                         /* display, window */ +                    prop, proptype,                 /* property, type */ +                    32,                             /* format: 32-bit datums */ +                    PropModeReplace,                /* mode */ +                    (unsigned char *) &motif_hints, /* data */ +                    PROP_MOTIF_WM_HINTS_ELEMENTS    /* nelements */ +                  ); +} + +  /*   * Create an RGB, double-buffered window.   * Return the window and context handles. @@ -479,13 +525,15 @@ make_window( Display *dpy, const char *name,     attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);     attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;     /* XXX this is a bad way to get a borderless window! */ -   attr.override_redirect = fullscreen; -   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect; +   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;     win = XCreateWindow( dpy, root, x, y, width, height,  		        0, visinfo->depth, InputOutput,  		        visinfo->visual, mask, &attr ); +   if (fullscreen) +      no_border(dpy, win); +     /* set hints and properties */     {        XSizeHints sizehints; diff --git a/progs/xdemos/glxgears_pixmap.c b/progs/xdemos/glxgears_pixmap.c new file mode 100644 index 0000000000..661d130e41 --- /dev/null +++ b/progs/xdemos/glxgears_pixmap.c @@ -0,0 +1,547 @@ +/* + * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved. + * Copyright (C) 2008  Red Hat, Inc   All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + *  + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + *  + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file glxgears_pixmap.c + * Yet-another-version of gears.  Originally ported to GLX by Brian Paul on + * 23 March 2001.  Modified to use fbconfigs by Ian Romanick on 10 Feb 2004. + * + * Command line options: + *    -info      print GL implementation information + * + * \author Brian Paul + * \author Ian Romanick <idr@us.ibm.com> + * \author Kristian Hoegsberg <krh@redhat.com> + */ + + +#define GLX_GLXEXT_PROTOTYPES + +#include <math.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <X11/Xlib.h> +#include <X11/keysym.h> +#include <GL/gl.h> +#include <GL/glx.h> +#include <GL/glxext.h> +#include <assert.h> +#include "pbutil.h" + +#define BENCHMARK + +#ifdef BENCHMARK + +/* XXX this probably isn't very portable */ + +#include <sys/time.h> +#include <unistd.h> + +/* return current time (in seconds) */ +static int +current_time(void) +{ +   struct timeval tv; +#ifdef __VMS +   (void) gettimeofday(&tv, NULL ); +#else +   struct timezone tz; +   (void) gettimeofday(&tv, &tz); +#endif +   return (int) tv.tv_sec; +} + +#else /*BENCHMARK*/ + +/* dummy */ +static int +current_time(void) +{ +   return 0; +} + +#endif /*BENCHMARK*/ + + + +#ifndef M_PI +#define M_PI 3.14159265 +#endif + + +static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0; +static GLint gear1, gear2, gear3; +static GLfloat angle = 0.0; + + +/* + * + *  Draw a gear wheel.  You'll probably want to call this function when + *  building a display list since we do a lot of trig here. + *  + *  Input:  inner_radius - radius of hole at center + *          outer_radius - radius at center of teeth + *          width - width of gear + *          teeth - number of teeth + *          tooth_depth - depth of tooth + */ +static void +gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, +     GLint teeth, GLfloat tooth_depth) +{ +   GLint i; +   GLfloat r0, r1, r2; +   GLfloat angle, da; +   GLfloat u, v, len; + +   r0 = inner_radius; +   r1 = outer_radius - tooth_depth / 2.0; +   r2 = outer_radius + tooth_depth / 2.0; + +   da = 2.0 * M_PI / teeth / 4.0; + +   glShadeModel(GL_FLAT); + +   glNormal3f(0.0, 0.0, 1.0); + +   /* draw front face */ +   glBegin(GL_QUAD_STRIP); +   for (i = 0; i <= teeth; i++) { +      angle = i * 2.0 * M_PI / teeth; +      glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); +      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); +      if (i < teeth) { +	 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); +	 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), +		    width * 0.5); +      } +   } +   glEnd(); + +   /* draw front sides of teeth */ +   glBegin(GL_QUADS); +   da = 2.0 * M_PI / teeth / 4.0; +   for (i = 0; i < teeth; i++) { +      angle = i * 2.0 * M_PI / teeth; + +      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); +      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); +      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), +		 width * 0.5); +      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), +		 width * 0.5); +   } +   glEnd(); + +   glNormal3f(0.0, 0.0, -1.0); + +   /* draw back face */ +   glBegin(GL_QUAD_STRIP); +   for (i = 0; i <= teeth; i++) { +      angle = i * 2.0 * M_PI / teeth; +      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); +      glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); +      if (i < teeth) { +	 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), +		    -width * 0.5); +	 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); +      } +   } +   glEnd(); + +   /* draw back sides of teeth */ +   glBegin(GL_QUADS); +   da = 2.0 * M_PI / teeth / 4.0; +   for (i = 0; i < teeth; i++) { +      angle = i * 2.0 * M_PI / teeth; + +      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), +		 -width * 0.5); +      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), +		 -width * 0.5); +      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); +      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); +   } +   glEnd(); + +   /* draw outward faces of teeth */ +   glBegin(GL_QUAD_STRIP); +   for (i = 0; i < teeth; i++) { +      angle = i * 2.0 * M_PI / teeth; + +      glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); +      glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); +      u = r2 * cos(angle + da) - r1 * cos(angle); +      v = r2 * sin(angle + da) - r1 * sin(angle); +      len = sqrt(u * u + v * v); +      u /= len; +      v /= len; +      glNormal3f(v, -u, 0.0); +      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); +      glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); +      glNormal3f(cos(angle), sin(angle), 0.0); +      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), +		 width * 0.5); +      glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), +		 -width * 0.5); +      u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da); +      v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da); +      glNormal3f(v, -u, 0.0); +      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), +		 width * 0.5); +      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), +		 -width * 0.5); +      glNormal3f(cos(angle), sin(angle), 0.0); +   } + +   glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5); +   glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5); + +   glEnd(); + +   glShadeModel(GL_SMOOTH); + +   /* draw inside radius cylinder */ +   glBegin(GL_QUAD_STRIP); +   for (i = 0; i <= teeth; i++) { +      angle = i * 2.0 * M_PI / teeth; +      glNormal3f(-cos(angle), -sin(angle), 0.0); +      glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); +      glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); +   } +   glEnd(); +} + + +static void +draw(void) +{ +   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + +   glPushMatrix(); +   glRotatef(view_rotx, 1.0, 0.0, 0.0); +   glRotatef(view_roty, 0.0, 1.0, 0.0); +   glRotatef(view_rotz, 0.0, 0.0, 1.0); + +   glPushMatrix(); +   glTranslatef(-3.0, -2.0, 0.0); +   glRotatef(angle, 0.0, 0.0, 1.0); +   glCallList(gear1); +   glPopMatrix(); + +   glPushMatrix(); +   glTranslatef(3.1, -2.0, 0.0); +   glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0); +   glCallList(gear2); +   glPopMatrix(); + +   glPushMatrix(); +   glTranslatef(-3.1, 4.2, 0.0); +   glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0); +   glCallList(gear3); +   glPopMatrix(); + +   glPopMatrix(); +} + + +struct gears { +   Window win; +   GLXContext ctx; +   Pixmap pixmap; +   GLXPixmap glxpixmap; +   GC gc; +   int width, height; +}; + + +/* new window size or exposure */ +static void +reshape(struct gears *gears, int width, int height) +{ +   gears->width = width; +   gears->height = height; +} + + +static void +init(int width, int height) +{ +   static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 }; +   static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 }; +   static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 }; +   static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 }; +   GLfloat h = (GLfloat) height / (GLfloat) width; + +   glLightfv(GL_LIGHT0, GL_POSITION, pos); +   glEnable(GL_CULL_FACE); +   glEnable(GL_LIGHTING); +   glEnable(GL_LIGHT0); +   glEnable(GL_DEPTH_TEST); + +   /* make the gears */ +   gear1 = glGenLists(1); +   glNewList(gear1, GL_COMPILE); +   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red); +   gear(1.0, 4.0, 1.0, 20, 0.7); +   glEndList(); + +   gear2 = glGenLists(1); +   glNewList(gear2, GL_COMPILE); +   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green); +   gear(0.5, 2.0, 2.0, 10, 0.7); +   glEndList(); + +   gear3 = glGenLists(1); +   glNewList(gear3, GL_COMPILE); +   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue); +   gear(1.3, 2.0, 0.5, 10, 0.7); +   glEndList(); + +   glEnable(GL_NORMALIZE); + +   glViewport(0, 0, (GLint) width, (GLint) height); +   glMatrixMode(GL_PROJECTION); +   glLoadIdentity(); +   glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0); +   glMatrixMode(GL_MODELVIEW); +   glLoadIdentity(); +   glTranslatef(0.0, 0.0, -40.0); +} + +/* + * Create an RGB, double-buffered window. + * Return the window and context handles. + */ +static void +make_window( Display *dpy, const char *name, +             int x, int y, int width, int height, struct gears *gears) +{ +   int attrib[] = { GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, +		    GLX_RENDER_TYPE,   GLX_RGBA_BIT, +		    GLX_RED_SIZE,      1, +		    GLX_GREEN_SIZE,    1, +		    GLX_BLUE_SIZE,     1, +		    GLX_DOUBLEBUFFER,  GL_FALSE, +		    GLX_DEPTH_SIZE,    1, +		    None }; +   GLXFBConfig * fbconfig; +   int num_configs; +   int scrnum; +   XSetWindowAttributes attr; +   unsigned long mask; +   Window root; +   XVisualInfo *visinfo; + +   gears->width = width; +   gears->height = height; + +   scrnum = DefaultScreen( dpy ); +   root = RootWindow( dpy, scrnum ); + +   fbconfig = glXChooseFBConfig(dpy, scrnum, attrib, & num_configs); +   if (fbconfig == NULL) { +      printf("Error: couldn't get an RGB, Double-buffered visual\n"); +      exit(1); +   } + +   /* window attributes */ +   visinfo = glXGetVisualFromFBConfig(dpy, fbconfig[0]); +   assert(visinfo != NULL); +   attr.background_pixel = 0; +   attr.border_pixel = 0; +   attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone); +   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; +   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; + +   gears->win = XCreateWindow( dpy, root, 0, 0, width, height, +			       0, visinfo->depth, InputOutput, +			       visinfo->visual, mask, &attr ); + +   /* set hints and properties */ +   { +      XSizeHints sizehints; +      sizehints.x = x; +      sizehints.y = y; +      sizehints.width  = width; +      sizehints.height = height; +      sizehints.flags = USSize | USPosition; +      XSetNormalHints(dpy, gears->win, &sizehints); +      XSetStandardProperties(dpy, gears->win, name, name, +                              None, (char **)NULL, 0, &sizehints); +   } + +   gears->gc = XCreateGC(dpy, gears->win, 0, NULL); + +   gears->pixmap = XCreatePixmap(dpy, gears->win, +				 width, height, visinfo->depth); +   if (!gears->pixmap) { +      printf("Error: XCreatePixmap failed\n"); +      exit(-1); +   } + +   gears->glxpixmap = glXCreatePixmap(dpy, fbconfig[0], gears->pixmap, NULL); +   if (!gears->glxpixmap) { +      printf("Error: glXCreatePixmap failed\n"); +      exit(-1); +   } + +   gears->ctx = glXCreateNewContext(dpy, fbconfig[0], +				    GLX_RGBA_TYPE, NULL, GL_TRUE); +   if (!gears->ctx) { +      printf("Error: glXCreateNewContext failed\n"); +      exit(1); +   } + +   XFree(fbconfig); +} + + +static void +event_loop(Display *dpy, struct gears *gears) +{ +   int x, y; + +   while (1) { +      while (XPending(dpy) > 0) { +         XEvent event; +         XNextEvent(dpy, &event); +         switch (event.type) { +	 case Expose: +            /* we'll redraw below */ +	    break; +	 case ConfigureNotify: +	    reshape(gears, event.xconfigure.width, event.xconfigure.height); +	    break; +         case KeyPress: +            { +               char buffer[10]; +               int r, code; +               code = XLookupKeysym(&event.xkey, 0); +               if (code == XK_Left) { +                  view_roty += 5.0; +               } +               else if (code == XK_Right) { +                  view_roty -= 5.0; +               } +               else if (code == XK_Up) { +                  view_rotx += 5.0; +               } +               else if (code == XK_Down) { +                  view_rotx -= 5.0; +               } +               else { +                  r = XLookupString(&event.xkey, buffer, sizeof(buffer), +                                    NULL, NULL); +                  if (buffer[0] == 27) { +                     /* escape */ +                     return; +                  } +               } +            } +         } +      } + +      /* next frame */ +      angle += 2.0; + +      draw(); +      glFinish(); + +      for (x = 0; x < gears->width; x += 100) +         for (y = 0; y < gears->width; y += 100) +            XCopyArea(dpy, gears->pixmap, gears->win, gears->gc, +		      50, 50, 100, 100, x, y); + +      /* calc framerate */ +      { +         static int t0 = -1; +         static int frames = 0; +         int t = current_time(); + +         if (t0 < 0) +            t0 = t; + +         frames++; + +         if (t - t0 >= 5.0) { +            GLfloat seconds = t - t0; +            GLfloat fps = frames / seconds; +            printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds, +                   fps); +            t0 = t; +            frames = 0; +         } +      } +   } +} + + +int +main(int argc, char *argv[]) +{ +   Display *dpy; +   const char *dpyName = NULL; +   GLboolean printInfo = GL_FALSE; +   struct gears gears; +   int i, width = 200, height = 200; + +   for (i = 1; i < argc; i++) { +      if (strcmp(argv[i], "-display") == 0) { +         dpyName = argv[i+1]; +         i++; +      } +      else if (strcmp(argv[i], "-info") == 0) { +         printInfo = GL_TRUE; +      } +   } + +   dpy = XOpenDisplay(dpyName); +   if (!dpy) { +      printf("Error: couldn't open display %s\n", XDisplayName(dpyName)); +      return -1; +   } + +   make_window(dpy, "glxgears", 0, 0, width, height, &gears); +   XMapWindow(dpy, gears.win); +   glXMakeCurrent(dpy, gears.glxpixmap, gears.ctx); + +   if (printInfo) { +      printf("GL_RENDERER   = %s\n", (char *) glGetString(GL_RENDERER)); +      printf("GL_VERSION    = %s\n", (char *) glGetString(GL_VERSION)); +      printf("GL_VENDOR     = %s\n", (char *) glGetString(GL_VENDOR)); +      printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS)); +   } + +   init(width, height); + +   event_loop(dpy, &gears); + +   glXDestroyContext(dpy, gears.ctx); +   XDestroyWindow(dpy, gears.win); +   glXDestroyPixmap(dpy, gears.pixmap); +   XFreePixmap(dpy, gears.pixmap); +   XCloseDisplay(dpy); + +   return 0; +} diff --git a/progs/xdemos/glxinfo.c b/progs/xdemos/glxinfo.c index 3e8e0be520..445d3ea94b 100644 --- a/progs/xdemos/glxinfo.c +++ b/progs/xdemos/glxinfo.c @@ -52,6 +52,13 @@  #define GLX_TRANSPARENT_RGB 0x8008  #endif +#ifndef GLX_RGBA_BIT +#define GLX_RGBA_BIT			0x00000001 +#endif + +#ifndef GLX_COLOR_INDEX_BIT +#define GLX_COLOR_INDEX_BIT		0x00000002 +#endif  typedef enum  { @@ -81,7 +88,7 @@ struct visual_attribs     int transparentIndexValue;     int bufferSize;     int level; -   int rgba; +   int render_type;     int doubleBuffer;     int stereo;     int auxBuffers; @@ -388,20 +395,60 @@ print_screen_info(Display *dpy, int scrnum, Bool allowDirect, GLboolean limits)     XSetWindowAttributes attr;     unsigned long mask;     Window root; -   GLXContext ctx; +   GLXContext ctx = NULL;     XVisualInfo *visinfo;     int width = 100, height = 100;     root = RootWindow(dpy, scrnum);     visinfo = glXChooseVisual(dpy, scrnum, attribSingle); -   if (!visinfo) { +   if (!visinfo)        visinfo = glXChooseVisual(dpy, scrnum, attribDouble); -      if (!visinfo) { -         fprintf(stderr, "Error: couldn't find RGB GLX visual\n"); -         return; + +   if (visinfo) +      ctx = glXCreateContext( dpy, visinfo, NULL, allowDirect ); + +#ifdef GLX_VERSION_1_3 +   { +      int fbAttribSingle[] = { +	 GLX_RENDER_TYPE,   GLX_RGBA_BIT, +	 GLX_RED_SIZE,      1, +	 GLX_GREEN_SIZE,    1, +	 GLX_BLUE_SIZE,     1, +	 GLX_DOUBLEBUFFER,  GL_TRUE, +	 None }; +      int fbAttribDouble[] = { +	 GLX_RENDER_TYPE,   GLX_RGBA_BIT, +	 GLX_RED_SIZE,      1, +	 GLX_GREEN_SIZE,    1, +	 GLX_BLUE_SIZE,     1, +	 None }; +      GLXFBConfig *configs = NULL; +      int nConfigs; + +      if (!visinfo) +	 configs = glXChooseFBConfig(dpy, scrnum, fbAttribSingle, &nConfigs); +      if (!visinfo) +	 configs = glXChooseFBConfig(dpy, scrnum, fbAttribDouble, &nConfigs); + +      if (configs) { +	 visinfo = glXGetVisualFromFBConfig(dpy, configs[0]); +	 ctx = glXCreateNewContext(dpy, configs[0], GLX_RGBA_TYPE, NULL, allowDirect); +	 XFree(configs);        }     } +#endif + +   if (!visinfo) { +      fprintf(stderr, "Error: couldn't find RGB GLX visual or fbconfig\n"); +      return; +   } + +   if (!ctx) { +      fprintf(stderr, "Error: glXCreateContext failed\n"); +      XFree(visinfo); +      return; +   }     attr.background_pixel = 0;     attr.border_pixel = 0; @@ -412,14 +459,6 @@ print_screen_info(Display *dpy, int scrnum, Bool allowDirect, GLboolean limits)  		       0, visinfo->depth, InputOutput,  		       visinfo->visual, mask, &attr); -   ctx = glXCreateContext( dpy, visinfo, NULL, allowDirect ); -   if (!ctx) { -      fprintf(stderr, "Error: glXCreateContext failed\n"); -      XFree(visinfo); -      XDestroyWindow(dpy, win); -      return; -   } -     if (glXMakeCurrent(dpy, win, ctx)) {        const char *serverVendor = glXQueryServerString(dpy, scrnum, GLX_VENDOR);        const char *serverVersion = glXQueryServerString(dpy, scrnum, GLX_VERSION); @@ -483,6 +522,13 @@ print_screen_info(Display *dpy, int scrnum, Bool allowDirect, GLboolean limits)        printf("OpenGL vendor string: %s\n", glVendor);        printf("OpenGL renderer string: %s\n", glRenderer);        printf("OpenGL version string: %s\n", glVersion); +#ifdef GL_VERSION_2_0 +      if (glVersion[0] >= '2' && glVersion[1] == '.') { +         char *v = (char *) glGetString(GL_SHADING_LANGUAGE_VERSION); +         printf("OpenGL shading language version string: %s\n", v); +      } +#endif +        printf("OpenGL extensions:\n");        print_extension_list(glExtensions);        if (limits) @@ -541,12 +587,27 @@ visual_class_abbrev(int cls)     }  } +static const char * +visual_render_type_name(int type) +{ +   switch (type) { +      case GLX_RGBA_BIT: +         return "rgba"; +      case GLX_COLOR_INDEX_BIT: +         return "ci"; +      case GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT: +         return "rgba|ci"; +      default: +         return ""; +      } +} -static void +static GLboolean  get_visual_attribs(Display *dpy, XVisualInfo *vInfo,                     struct visual_attribs *attribs)  {     const char *ext = glXQueryExtensionsString(dpy, vInfo->screen); +   int rgba;     memset(attribs, 0, sizeof(struct visual_attribs)); @@ -563,11 +624,17 @@ get_visual_attribs(Display *dpy, XVisualInfo *vInfo,     attribs->colormapSize = vInfo->colormap_size;     attribs->bitsPerRGB = vInfo->bits_per_rgb; -   if (glXGetConfig(dpy, vInfo, GLX_USE_GL, &attribs->supportsGL) != 0) -      return; +   if (glXGetConfig(dpy, vInfo, GLX_USE_GL, &attribs->supportsGL) != 0 || +       !attribs->supportsGL) +      return GL_FALSE;     glXGetConfig(dpy, vInfo, GLX_BUFFER_SIZE, &attribs->bufferSize);     glXGetConfig(dpy, vInfo, GLX_LEVEL, &attribs->level); -   glXGetConfig(dpy, vInfo, GLX_RGBA, &attribs->rgba); +   glXGetConfig(dpy, vInfo, GLX_RGBA, &rgba); +   if (rgba) +      attribs->render_type = GLX_RGBA_BIT; +   else +      attribs->render_type = GLX_COLOR_INDEX_BIT; +        glXGetConfig(dpy, vInfo, GLX_DOUBLEBUFFER, &attribs->doubleBuffer);     glXGetConfig(dpy, vInfo, GLX_STEREO, &attribs->stereo);     glXGetConfig(dpy, vInfo, GLX_AUX_BUFFERS, &attribs->auxBuffers); @@ -596,7 +663,7 @@ get_visual_attribs(Display *dpy, XVisualInfo *vInfo,     /* multisample attribs */  #ifdef GLX_ARB_multisample -   if (ext && strstr(ext, "GLX_ARB_multisample") == 0) { +   if (ext && strstr(ext, "GLX_ARB_multisample")) {        glXGetConfig(dpy, vInfo, GLX_SAMPLE_BUFFERS_ARB, &attribs->numMultisample);        glXGetConfig(dpy, vInfo, GLX_SAMPLES_ARB, &attribs->numSamples);     } @@ -616,8 +683,97 @@ get_visual_attribs(Display *dpy, XVisualInfo *vInfo,  #else     attribs->visualCaveat = 0;  #endif + +   return GL_TRUE;  } +#ifdef GLX_VERSION_1_3 + +static int +glx_token_to_visual_class(int visual_type) +{ +   switch (visual_type) { +   case GLX_TRUE_COLOR: +      return TrueColor; +   case GLX_DIRECT_COLOR: +      return DirectColor; +   case GLX_PSEUDO_COLOR: +      return PseudoColor; +   case GLX_STATIC_COLOR: +      return StaticColor; +   case GLX_GRAY_SCALE: +      return GrayScale; +   case GLX_STATIC_GRAY: +      return StaticGray; +   case GLX_NONE: +   default: +      return None; +   } +} + +static GLboolean +get_fbconfig_attribs(Display *dpy, GLXFBConfig fbconfig, +		     struct visual_attribs *attribs) +{ +   int visual_type; + +   memset(attribs, 0, sizeof(struct visual_attribs)); + +   glXGetFBConfigAttrib(dpy, fbconfig, GLX_FBCONFIG_ID, &attribs->id); + +#if 0 +   attribs->depth = vInfo->depth; +   attribs->redMask = vInfo->red_mask; +   attribs->greenMask = vInfo->green_mask; +   attribs->blueMask = vInfo->blue_mask; +   attribs->colormapSize = vInfo->colormap_size; +   attribs->bitsPerRGB = vInfo->bits_per_rgb; +#endif + +   glXGetFBConfigAttrib(dpy, fbconfig, GLX_X_VISUAL_TYPE, &visual_type); +   attribs->klass = glx_token_to_visual_class(visual_type); + +   glXGetFBConfigAttrib(dpy, fbconfig, GLX_BUFFER_SIZE, &attribs->bufferSize); +   glXGetFBConfigAttrib(dpy, fbconfig, GLX_LEVEL, &attribs->level); +   glXGetFBConfigAttrib(dpy, fbconfig, GLX_RENDER_TYPE, &attribs->render_type); +   glXGetFBConfigAttrib(dpy, fbconfig, GLX_DOUBLEBUFFER, &attribs->doubleBuffer); +   glXGetFBConfigAttrib(dpy, fbconfig, GLX_STEREO, &attribs->stereo); +   glXGetFBConfigAttrib(dpy, fbconfig, GLX_AUX_BUFFERS, &attribs->auxBuffers); + +   glXGetFBConfigAttrib(dpy, fbconfig, GLX_RED_SIZE, &attribs->redSize); +   glXGetFBConfigAttrib(dpy, fbconfig, GLX_GREEN_SIZE, &attribs->greenSize); +   glXGetFBConfigAttrib(dpy, fbconfig, GLX_BLUE_SIZE, &attribs->blueSize); +   glXGetFBConfigAttrib(dpy, fbconfig, GLX_ALPHA_SIZE, &attribs->alphaSize); +   glXGetFBConfigAttrib(dpy, fbconfig, GLX_DEPTH_SIZE, &attribs->depthSize); +   glXGetFBConfigAttrib(dpy, fbconfig, GLX_STENCIL_SIZE, &attribs->stencilSize); + +   glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize); +   glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize); +   glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize); +   glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize); + +   /* get transparent pixel stuff */ +   glXGetFBConfigAttrib(dpy, fbconfig,GLX_TRANSPARENT_TYPE, &attribs->transparentType); +   if (attribs->transparentType == GLX_TRANSPARENT_RGB) { +     glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_RED_VALUE, &attribs->transparentRedValue); +     glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_GREEN_VALUE, &attribs->transparentGreenValue); +     glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_BLUE_VALUE, &attribs->transparentBlueValue); +     glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_ALPHA_VALUE, &attribs->transparentAlphaValue); +   } +   else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) { +     glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue); +   } + +   glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLE_BUFFERS, &attribs->numMultisample); +   glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLES, &attribs->numSamples); +   glXGetFBConfigAttrib(dpy, fbconfig, GLX_CONFIG_CAVEAT, &attribs->visualCaveat); + +   return GL_TRUE; +} + +#endif + +  static void  print_visual_attribs_verbose(const struct visual_attribs *attribs) @@ -625,7 +781,8 @@ print_visual_attribs_verbose(const struct visual_attribs *attribs)     printf("Visual ID: %x  depth=%d  class=%s\n",            attribs->id, attribs->depth, visual_class_name(attribs->klass));     printf("    bufferSize=%d level=%d renderType=%s doubleBuffer=%d stereo=%d\n", -          attribs->bufferSize, attribs->level, attribs->rgba ? "rgba" : "ci", +          attribs->bufferSize, attribs->level, +	  visual_render_type_name(attribs->render_type),            attribs->doubleBuffer, attribs->stereo);     printf("    rgba: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n",            attribs->redSize, attribs->greenSize, @@ -683,16 +840,17 @@ print_visual_attribs_short(const struct visual_attribs *attribs)     caveat = "None";  #endif  -   printf("0x%2x %2d %2s %2d %2d %2d %1s %2s %2s %2d %2d %2d %2d %2d %2d %2d", +   printf("0x%02x %2d %2s %2d %2d %2d %c%c %c  %c %2d %2d %2d %2d %2d %2d %2d",            attribs->id,            attribs->depth,            visual_class_abbrev(attribs->klass),            attribs->transparentType != GLX_NONE,            attribs->bufferSize,            attribs->level, -          attribs->rgba ? "r" : "c", -          attribs->doubleBuffer ? "y" : ".", -          attribs->stereo ? "y" : ".", +          (attribs->render_type & GLX_RGBA_BIT) ? 'r' : ' ', +          (attribs->render_type & GLX_COLOR_INDEX_BIT) ? 'c' : ' ', +          attribs->doubleBuffer ? 'y' : '.', +          attribs->stereo ? 'y' : '.',            attribs->redSize, attribs->greenSize,            attribs->blueSize, attribs->alphaSize,            attribs->auxBuffers, @@ -728,7 +886,7 @@ print_visual_attribs_long(const struct visual_attribs *attribs)            attribs->transparentType != GLX_NONE,            attribs->bufferSize,            attribs->level, -          attribs->rgba ? "rgba" : "ci  ", +          visual_render_type_name(attribs->render_type),            attribs->doubleBuffer,            attribs->stereo,            attribs->redSize, attribs->greenSize, @@ -751,42 +909,86 @@ print_visual_info(Display *dpy, int scrnum, InfoMode mode)  {     XVisualInfo theTemplate;     XVisualInfo *visuals; -   int numVisuals; +   int numVisuals, numGlxVisuals;     long mask;     int i; +   struct visual_attribs attribs;     /* get list of all visuals on this screen */     theTemplate.screen = scrnum;     mask = VisualScreenMask;     visuals = XGetVisualInfo(dpy, mask, &theTemplate, &numVisuals); -   if (mode == Verbose) { -      for (i = 0; i < numVisuals; i++) { -         struct visual_attribs attribs; -         get_visual_attribs(dpy, &visuals[i], &attribs); -         print_visual_attribs_verbose(&attribs); -      } +   numGlxVisuals = 0; +   for (i = 0; i < numVisuals; i++) { +      if (get_visual_attribs(dpy, &visuals[i], &attribs)) +	 numGlxVisuals++;     } -   else if (mode == Normal) { + +   if (numGlxVisuals == 0) +      return; + +   printf("%d GLX Visuals\n", numGlxVisuals); + +   if (mode == Normal)        print_visual_attribs_short_header(); -      for (i = 0; i < numVisuals; i++) { -         struct visual_attribs attribs; -         get_visual_attribs(dpy, &visuals[i], &attribs); +   else if (mode == Wide) +      print_visual_attribs_long_header(); + +   for (i = 0; i < numVisuals; i++) { +      if (!get_visual_attribs(dpy, &visuals[i], &attribs)) +	 continue; + +      if (mode == Verbose) +	 print_visual_attribs_verbose(&attribs); +      else if (mode == Normal)           print_visual_attribs_short(&attribs); -      } +      else if (mode == Wide)  +         print_visual_attribs_long(&attribs);     } -   else if (mode == Wide) { +   printf("\n"); + +   XFree(visuals); +} + +#ifdef GLX_VERSION_1_3 + +static void +print_fbconfig_info(Display *dpy, int scrnum, InfoMode mode) +{ +   int numFBConfigs; +   struct visual_attribs attribs; +   GLXFBConfig *fbconfigs; +   int i; + +   /* get list of all fbconfigs on this screen */ +   fbconfigs = glXGetFBConfigs(dpy, scrnum, &numFBConfigs); + +   if (numFBConfigs == 0) +      return; + +   printf("%d GLXFBConfigs:\n", numFBConfigs); +   if (mode == Normal) +      print_visual_attribs_short_header(); +   else if (mode == Wide)        print_visual_attribs_long_header(); -      for (i = 0; i < numVisuals; i++) { -         struct visual_attribs attribs; -         get_visual_attribs(dpy, &visuals[i], &attribs); + +   for (i = 0; i < numFBConfigs; i++) { +      get_fbconfig_attribs(dpy, fbconfigs[i], &attribs); + +      if (mode == Verbose)  +         print_visual_attribs_verbose(&attribs); +      else if (mode == Normal) +	 print_visual_attribs_short(&attribs); +      else if (mode == Wide)           print_visual_attribs_long(&attribs); -      }     } +   printf("\n"); -   XFree(visuals); +   XFree(fbconfigs);  } +#endif  /*   * Stand-alone Mesa doesn't really implement the GLX protocol so it @@ -860,7 +1062,7 @@ find_best_visual(Display *dpy, int scrnum)        /* see if this vis is better than bestVis */        if ((!bestVis.supportsGL && vis.supportsGL) ||            (bestVis.visualCaveat != GLX_NONE_EXT) || -          (!bestVis.rgba && vis.rgba) || +          (!(bestVis.render_type & GLX_RGBA_BIT) && (vis.render_type & GLX_RGBA_BIT)) ||            (!bestVis.doubleBuffer && vis.doubleBuffer) ||            (bestVis.redSize < vis.redSize) ||            (bestVis.greenSize < vis.greenSize) || @@ -957,6 +1159,9 @@ main(int argc, char *argv[])           print_screen_info(dpy, scrnum, allowDirect, limits);           printf("\n");           print_visual_info(dpy, scrnum, mode); +#ifdef GLX_VERSION_1_3 +         print_fbconfig_info(dpy, scrnum, mode); +#endif           if (scrnum + 1 < numScreens)              printf("\n\n");        } diff --git a/progs/xdemos/glxsnoop.c b/progs/xdemos/glxsnoop.c new file mode 100644 index 0000000000..2e951345b5 --- /dev/null +++ b/progs/xdemos/glxsnoop.c @@ -0,0 +1,377 @@ +/** + * Display/snoop the z/stencil/back/front buffers of another app's window. + * Also, an example of the need for shared ancillary renderbuffers. + * + * Hint: use 'xwininfo' to get a window's ID. + * + * Brian Paul + * 11 Oct 2007 + */ + +#define GL_GLEXT_PROTOTYPES + +#include <GL/gl.h> +#include <GL/glx.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <X11/keysym.h> + + +#define Z_BUFFER 1 +#define STENCIL_BUFFER 2 +#define BACK_BUFFER 3 +#define FRONT_BUFFER 4 + + +static int Buffer = BACK_BUFFER; +static int WindowID = 0; +static const char *DisplayName = NULL; +static GLXContext Context = 0; +static int Width, Height; + + +/** + * Grab the z/stencil/back/front image from the srcWin and display it + * (possibly converted to grayscale) in the dstWin. + */ +static void +redraw(Display *dpy, Window srcWin, Window dstWin ) +{ +   GLubyte *image = malloc(Width * Height * 4); + +   glXMakeCurrent(dpy, srcWin, Context); +   glPixelStorei(GL_PACK_ALIGNMENT, 1); +   if (Buffer == BACK_BUFFER) { +      glReadBuffer(GL_BACK); +      glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, image); +   } +   else if (Buffer == FRONT_BUFFER) { +      glReadBuffer(GL_FRONT); +      glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, image); +   } +   else if (Buffer == Z_BUFFER) { +      GLfloat *z = malloc(Width * Height * sizeof(GLfloat)); +      int i; +      glReadPixels(0, 0, Width, Height, GL_DEPTH_COMPONENT, GL_FLOAT, z); +      for (i = 0; i < Width * Height; i++) { +         image[i*4+0] = +         image[i*4+1] = +         image[i*4+2] = (GLint) (255.0 * z[i]); +         image[i*4+3] = 255; +      } +      free(z); +   } +   else if (Buffer == STENCIL_BUFFER) { +      GLubyte *sten = malloc(Width * Height * sizeof(GLubyte)); +      int i, min = 100, max = -1; +      float step; +      int sz; +      glGetIntegerv(GL_STENCIL_BITS, &sz); +      glReadPixels(0, 0, Width, Height, +                   GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, sten); +      /* find min/max for converting stencil to grayscale */ +      for (i = 0; i < Width * Height; i++) { +         if (sten[i] < min) +            min = sten[i]; +         if (sten[i] > max) +            max = sten[i]; +      } +      if (min == max) +         step = 0; +      else +         step = 255.0 / (float) (max - min); +      for (i = 0; i < Width * Height; i++) { +         image[i*4+0] = +         image[i*4+1] = +         image[i*4+2] = (GLint) ((sten[i] - min) * step); +         image[i*4+3] = 255; +      } +      free(sten); +   } + +   glXMakeCurrent(dpy, dstWin, Context); +   glWindowPos2iARB(0, 0); +   glDrawBuffer(GL_FRONT); +   glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, image); +   glFlush(); + +   free(image); +} + + +static void +set_window_title(Display *dpy, Window win, const char *title) +{ +   XSizeHints sizehints; +   sizehints.flags = 0; +   XSetStandardProperties(dpy, win, title, title, +                          None, (char **)NULL, 0, &sizehints); +} + + +static Window +make_gl_window(Display *dpy, XVisualInfo *visinfo, int width, int height) +{ +   int scrnum; +   XSetWindowAttributes attr; +   unsigned long mask; +   Window root; +   Window win; +   int x = 0, y = 0; +   char *name = NULL; + +   scrnum = DefaultScreen( dpy ); +   root = RootWindow( dpy, scrnum ); + +   /* window attributes */ +   attr.background_pixel = 0; +   attr.border_pixel = 0; +   attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone); +   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; +   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; + +   win = XCreateWindow( dpy, root, x, y, width, height, +		        0, visinfo->depth, InputOutput, +		        visinfo->visual, mask, &attr ); + +   /* set hints and properties */ +   { +      XSizeHints sizehints; +      sizehints.x = x; +      sizehints.y = y; +      sizehints.width  = width; +      sizehints.height = height; +      sizehints.flags = USSize | USPosition; +      XSetNormalHints(dpy, win, &sizehints); +      XSetStandardProperties(dpy, win, name, name, +                              None, (char **)NULL, 0, &sizehints); +   } + +   return win; +} + + +static void +update_window_title(Display *dpy, Window win) +{ +   char title[1000], *buf; + +   switch (Buffer) { +   case Z_BUFFER: +      buf = "Z"; +      break; +   case STENCIL_BUFFER: +      buf = "Stencil"; +      break; +   case BACK_BUFFER: +      buf = "Back"; +      break; +   case FRONT_BUFFER: +      buf = "Front"; +      break; +   default: +      buf = ""; +   } + +   sprintf(title, "glxsnoop window 0x%x (%s buffer)", (int) WindowID, buf); + +   set_window_title(dpy, win, title); +} + + +static void +keypress(Display *dpy, Window win, char key) +{ +   switch (key) { +   case 27: +      /* escape */ +      exit(0); +      break; +   case 's': +      Buffer = STENCIL_BUFFER; +      break; +   case 'z': +      Buffer = Z_BUFFER; +      break; +   case 'f': +      Buffer = FRONT_BUFFER; +      break; +   case 'b': +      Buffer = BACK_BUFFER; +      break; +   default: +      return; +   } + +   update_window_title(dpy, win); +   redraw(dpy, WindowID, win); +} + + +static void +event_loop(Display *dpy, Window win) +{ +   XEvent event; + +   while (1) { +      XNextEvent( dpy, &event ); + +      switch (event.type) { +      case Expose: +         redraw(dpy, WindowID, win); +         break; +      case ConfigureNotify: +         /*resize( event.xconfigure.width, event.xconfigure.height );*/ +         break; +      case KeyPress: +         { +            char buffer[10]; +            int r, code; +            code = XLookupKeysym(&event.xkey, 0); +            if (code == XK_Left) { +            } +            else { +               r = XLookupString(&event.xkey, buffer, sizeof(buffer), +                                 NULL, NULL); +               keypress(dpy, win, buffer[0]); +            } +         } +      default: +         /* nothing */ +         ; +      } +   } +} + + +static VisualID +get_window_visualid(Display *dpy, Window win) +{ +   XWindowAttributes attr; + +   if (XGetWindowAttributes(dpy, win, &attr)) { +      return attr.visual->visualid; +   } +   else { +      return 0; +   } +} + + +static void +get_window_size(Display *dpy, Window win, int *w, int *h) +{ +   XWindowAttributes attr; + +   if (XGetWindowAttributes(dpy, win, &attr)) { +      *w = attr.width; +      *h = attr.height; +   } +   else { +      *w = *h = 0; +   } +} + + +static XVisualInfo * +visualid_to_visualinfo(Display *dpy, VisualID vid) +{ +   XVisualInfo *vinfo, templ; +   long mask; +   int n; + +   templ.visualid = vid; +   mask = VisualIDMask; + +   vinfo = XGetVisualInfo(dpy, mask, &templ, &n); +   return vinfo; +} + + +static void +key_usage(void) +{ +   printf("Keyboard:\n"); +   printf("  z - display Z buffer\n"); +   printf("  s - display stencil buffer\n"); +   printf("  f - display front color buffer\n"); +   printf("  b - display back buffer\n"); +} + + +static void +usage(void) +{ +   printf("Usage: glxsnoop [-display dpy] windowID\n"); +   key_usage(); +} + + +static void +parse_opts(int argc, char *argv[]) +{ +   int i; + +   for (i = 1; i < argc; i++) { +      if (strcmp(argv[i], "-h") == 0) { +         usage(); +         exit(0); +      } +      else if (strcmp(argv[i], "-display") == 0) { +         DisplayName = argv[i + 1]; +         i++; +      } +      else { +         if (argv[i][0] == '0' && argv[i][1] == 'x') { +            /* hex */ +            WindowID = strtol(argv[i], NULL, 16); +         } +         else { +            WindowID = atoi(argv[i]); +         } +         break; +      } +   } + +   if (!WindowID) { +      usage(); +      exit(0); +   } +} + + +int +main( int argc, char *argv[] ) +{ +   Display *dpy; +   VisualID vid; +   XVisualInfo *visinfo; +   Window win; + +   parse_opts(argc, argv); + +   key_usage(); + +   dpy = XOpenDisplay(DisplayName); + +   /* find the VisualID for the named window */ +   vid = get_window_visualid(dpy, WindowID); +   get_window_size(dpy, WindowID, &Width, &Height); + +   visinfo = visualid_to_visualinfo(dpy, vid); + +   Context = glXCreateContext( dpy, visinfo, NULL, True ); +   if (!Context) { +      printf("Error: glXCreateContext failed\n"); +      exit(1); +   } + +   win = make_gl_window(dpy, visinfo, Width, Height); +   XMapWindow(dpy, win); +   update_window_title(dpy, win); + +   event_loop( dpy, win ); + +   return 0; +} diff --git a/progs/xdemos/glxswapcontrol.c b/progs/xdemos/glxswapcontrol.c index d9be984be5..2c51801989 100644 --- a/progs/xdemos/glxswapcontrol.c +++ b/progs/xdemos/glxswapcontrol.c @@ -121,7 +121,7 @@ static char ** extension_table = NULL;  static unsigned num_extensions;  static GLboolean use_ztrick = GL_FALSE; -static GLfloat   aspect; +static GLfloat aspectX = 1.0f, aspectY = 1.0f;  /*   * @@ -313,13 +313,13 @@ draw(void)        glMatrixMode(GL_PROJECTION);        glLoadIdentity(); -      glFrustum(-1.0, 1.0, -aspect, aspect, 5.0, 60.0); +      glFrustum(-aspectX, aspectX, -aspectY, aspectY, 5.0, 60.0);        glEnable(GL_LIGHTING);        glMatrixMode(GL_MODELVIEW);        glLoadIdentity(); -      glTranslatef(0.0, 0.0, -40.0); +      glTranslatef(0.0, 0.0, -45.0);     }     else {        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -356,17 +356,23 @@ draw(void)  static void  reshape(int width, int height)  { -   aspect = (GLfloat) height / (GLfloat) width; +   if (width > height) { +      aspectX = (GLfloat) width / (GLfloat) height; +      aspectY = 1.0; +   } +   else { +      aspectX = 1.0; +      aspectY = (GLfloat) height / (GLfloat) width; +   } -        glViewport(0, 0, (GLint) width, (GLint) height);     glMatrixMode(GL_PROJECTION);     glLoadIdentity(); -   glFrustum(-1.0, 1.0, -aspect, aspect, 5.0, 60.0); +   glFrustum(-aspectX, aspectX, -aspectY, aspectY, 5.0, 60.0);     glMatrixMode(GL_MODELVIEW);     glLoadIdentity(); -   glTranslatef(0.0, 0.0, -40.0); +   glTranslatef(0.0, 0.0, -45.0);  } @@ -407,13 +413,59 @@ init(void)  } +/** + * Remove window border/decorations. + */ +static void +no_border( Display *dpy, Window w) +{ +   static const unsigned MWM_HINTS_DECORATIONS = (1 << 1); +   static const int PROP_MOTIF_WM_HINTS_ELEMENTS = 5; + +   typedef struct +   { +      unsigned long       flags; +      unsigned long       functions; +      unsigned long       decorations; +      long                inputMode; +      unsigned long       status; +   } PropMotifWmHints; + +   PropMotifWmHints motif_hints; +   Atom prop, proptype; +   unsigned long flags = 0; + +   /* setup the property */ +   motif_hints.flags = MWM_HINTS_DECORATIONS; +   motif_hints.decorations = flags; + +   /* get the atom for the property */ +   prop = XInternAtom( dpy, "_MOTIF_WM_HINTS", True ); +   if (!prop) { +      /* something went wrong! */ +      return; +   } + +   /* not sure this is correct, seems to work, XA_WM_HINTS didn't work */ +   proptype = prop; + +   XChangeProperty( dpy, w,                         /* display, window */ +                    prop, proptype,                 /* property, type */ +                    32,                             /* format: 32-bit datums */ +                    PropModeReplace,                /* mode */ +                    (unsigned char *) &motif_hints, /* data */ +                    PROP_MOTIF_WM_HINTS_ELEMENTS    /* nelements */ +                  ); +} + +  /*   * Create an RGB, double-buffered window.   * Return the window and context handles.   */  static void  make_window( Display *dpy, const char *name, -             int x, int y, int width, int height, +             int x, int y, int width, int height, GLboolean fullscreen,               Window *winRet, GLXContext *ctxRet)  {     int attrib[] = { GLX_RGBA, @@ -434,6 +486,12 @@ make_window( Display *dpy, const char *name,     scrnum = DefaultScreen( dpy );     root = RootWindow( dpy, scrnum ); +   if (fullscreen) { +      x = y = 0; +      width = DisplayWidth( dpy, scrnum ); +      height = DisplayHeight( dpy, scrnum ); +   } +     visinfo = glXChooseVisual( dpy, scrnum, attrib );     if (!visinfo) {        printf("Error: couldn't get an RGB, Double-buffered visual\n"); @@ -464,6 +522,9 @@ make_window( Display *dpy, const char *name,                                None, (char **)NULL, 0, &sizehints);     } +   if (fullscreen) +      no_border(dpy, win); +     ctx = glXCreateContext( dpy, visinfo, NULL, True );     if (!ctx) {        printf("Error: glXCreateContext failed\n"); @@ -572,7 +633,6 @@ event_loop(Display *dpy, Window win)   * Display the refresh rate of the display using the GLX_OML_sync_control   * extension.   */ -  static void  show_refresh_rate( Display * dpy )  { @@ -599,7 +659,6 @@ show_refresh_rate( Display * dpy )   * \param string   String of GLX extensions.   * \sa is_extension_supported   */ -  static void  make_extension_table( const char * string )  { @@ -679,7 +738,6 @@ make_extension_table( const char * string )   * \return GL_TRUE of the extension is supported, GL_FALSE otherwise.   * \sa make_extension_table   */ -  static GLboolean  is_extension_supported( const char * ext )  { @@ -705,11 +763,12 @@ main(int argc, char *argv[])     int swap_interval = 1;     GLboolean do_swap_interval = GL_FALSE;     GLboolean force_get_rate = GL_FALSE; +   GLboolean fullscreen = GL_FALSE;     GLboolean printInfo = GL_FALSE;     int i;     PFNGLXSWAPINTERVALMESAPROC set_swap_interval = NULL;     PFNGLXGETSWAPINTERVALMESAPROC get_swap_interval = NULL; - +   int width = 300, height = 300;     for (i = 1; i < argc; i++) {        if (strcmp(argv[i], "-display") == 0 && i + 1 < argc) { @@ -731,6 +790,9 @@ main(int argc, char *argv[])  	  */  	 force_get_rate = GL_TRUE;        } +      else if (strcmp(argv[i], "-fullscreen") == 0) { +         fullscreen = GL_TRUE; +      }        else if (strcmp(argv[i], "-ztrick") == 0) {  	 use_ztrick = GL_TRUE;        } @@ -743,6 +805,7 @@ main(int argc, char *argv[])           printf("  -info                   Display GL information\n");           printf("  -swap N                 Swap no more than once per N vertical refreshes\n");           printf("  -forcegetrate           Try to use glXGetMscRateOML function\n"); +         printf("  -fullscreen             Full-screen window\n");           return 0;        }     } @@ -753,7 +816,7 @@ main(int argc, char *argv[])        return -1;     } -   make_window(dpy, "glxgears", 0, 0, 300, 300, &win, &ctx); +   make_window(dpy, "glxgears", 0, 0, width, height, fullscreen, &win, &ctx);     XMapWindow(dpy, win);     glXMakeCurrent(dpy, win, ctx); @@ -814,6 +877,11 @@ main(int argc, char *argv[])     init(); +   /* Set initial projection/viewing transformation. +    * same as glxgears.c +    */ +   reshape(width, height); +     event_loop(dpy, win);     glXDestroyContext(dpy, ctx); diff --git a/progs/xdemos/ipc.c b/progs/xdemos/ipc.c new file mode 100644 index 0000000000..c872d1641a --- /dev/null +++ b/progs/xdemos/ipc.c @@ -0,0 +1,264 @@ +/* Copyright (c) 2003 Tungsten Graphics, Inc. + *  + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files ("the + * Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions:  The above copyright notice, the Tungsten + * Graphics splash screen, and this permission notice shall be included + * in all copies or substantial portions of the Software.  THE SOFTWARE + * IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT + * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Simple IPC API + * Brian Paul + */ + + +#include <assert.h> +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <unistd.h> +#include <sys/socket.h> +#include "ipc.h" + +#if defined(IRIX) || defined(irix) +typedef int socklen_t; +#endif + +#define NO_DELAY 1 + +#define DEFAULT_MASTER_PORT 7011 + + +/* + * Return my hostname in <nameOut>. + * Return 1 for success, 0 for error. + */ +int +MyHostName(char *nameOut, int maxNameLength) +{ +    int k = gethostname(nameOut, maxNameLength); +    return k==0; +} + + +/* + * Create a socket attached to a port.  Later, we can call AcceptConnection + * on the socket returned from this function. + * Return the new socket number or -1 if error. + */ +int +CreatePort(int *port) +{ +    char hostname[1000]; +    struct sockaddr_in servaddr; +    struct hostent *hp; +    int so_reuseaddr = 1; +    int tcp_nodelay = 1; +    int sock, k; + +    /* create socket */ +    sock = socket(AF_INET, SOCK_STREAM, 0); +    assert(sock > 2); + +    /* get my host name */ +    k = gethostname(hostname, 1000); +    assert(k == 0); + +    /* get hostent info */ +    hp = gethostbyname(hostname); +    assert(hp); + +    /* initialize the servaddr struct */ +    memset(&servaddr, 0, sizeof(servaddr) ); +    servaddr.sin_family = AF_INET; +    servaddr.sin_port = htons((unsigned short) (*port)); +    memcpy((char *) &servaddr.sin_addr, hp->h_addr, +	   sizeof(servaddr.sin_addr)); + +    /* deallocate when we exit */ +    k = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, +		   (char *) &so_reuseaddr, sizeof(so_reuseaddr)); +    assert(k==0); + +    /* send packets immediately */ +#if NO_DELAY +    k = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, +		   (char *) &tcp_nodelay, sizeof(tcp_nodelay)); +    assert(k==0); +#endif + +    if (*port == 0) +        *port = DEFAULT_MASTER_PORT; + +    k = 1; +    while (k && (*port < 65534)) { +    	/* bind our address to the socket */ +    	servaddr.sin_port = htons((unsigned short) (*port)); +    	k = bind(sock, (struct sockaddr *) &servaddr, sizeof(servaddr)); +        if (k) +           *port = *port + 1; +    } + +#if 0 +    printf("###### Real Port: %d\n", *port); +#endif + +    /* listen for connections */ +    k = listen(sock, 100); +    assert(k == 0); + +    return sock; +} + + +/* + * Accept a connection on the named socket. + * Return a new socket for the new connection, or -1 if error. + */ +int +AcceptConnection(int socket) +{ +    struct sockaddr addr; +    socklen_t addrLen; +    int newSock; + +    addrLen = sizeof(addr); +    newSock = accept(socket, &addr, &addrLen); +    if (newSock == 1) +	return -1; +    else +	return newSock; +} + + +/* + * Contact the server running on the given host on the named port. + * Return socket number or -1 if error. + */ +int +Connect(const char *hostname, int port) +{ +    struct sockaddr_in servaddr; +    struct hostent *hp; +    int sock, k; +    int tcp_nodelay = 1; + +    assert(port); + +    sock = socket(AF_INET, SOCK_STREAM, 0); +    assert(sock >= 0); + +    hp = gethostbyname(hostname); +    assert(hp); + +    memset(&servaddr, 0, sizeof(servaddr)); +    servaddr.sin_family = AF_INET; +    servaddr.sin_port = htons((unsigned short) port); +    memcpy((char *) &servaddr.sin_addr, hp->h_addr, sizeof(servaddr.sin_addr)); + +    k = connect(sock, (struct sockaddr *) &servaddr, sizeof(servaddr)); +    if (k != 0) { +       perror("Connect:"); +       return -1; +    } + +#if NO_DELAY +    /* send packets immediately */ +    k = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, +		   (char *) &tcp_nodelay, sizeof(tcp_nodelay)); +    assert(k==0); +#endif + +    return sock; +} + + +void +CloseSocket(int socket) +{ +    close(socket); +} + + +int +SendData(int socket, const void *data, int bytes) +{ +    int sent = 0; +    int b; + +    while (sent < bytes) { +        b = write(socket, (char *) data + sent, bytes - sent); +        if (b <= 0) +            return -1; /* something broke */ +        sent += b; +    } +    return sent; +} + + +int +ReceiveData(int socket, void *data, int bytes) +{ +    int received = 0, b; + +    while (received < bytes) { +        b = read(socket, (char *) data + received, bytes - received); +        if (b <= 0) +            return -1; +        received += b; +    } +    return received; +} + + +int +SendString(int socket, const char *str) +{ +    const int len = strlen(str); +    int sent, b; + +    /* first, send a 4-byte length indicator */ +    b = write(socket, &len, sizeof(len)); +    if (b <= 0) +	return -1; + +    sent = SendData(socket, str, len); +    assert(sent == len); +    return sent; +} + + +int +ReceiveString(int socket, char *str, int maxLen) +{ +    int len, received, b; + +    /* first, read 4 bytes to see how long of string to receive */ +    b = read(socket, &len, sizeof(len)); +    if (b <= 0) +	return -1; + +    assert(len <= maxLen);  /* XXX fix someday */ +    assert(len >= 0); +    received = ReceiveData(socket, str, len); +    assert(received != -1); +    assert(received == len); +    str[len] = 0; +    return received; +} diff --git a/progs/xdemos/ipc.h b/progs/xdemos/ipc.h new file mode 100644 index 0000000000..3f434457c6 --- /dev/null +++ b/progs/xdemos/ipc.h @@ -0,0 +1,16 @@ +#ifndef IPC_H +#define IPC_H + + +extern int MyHostName(char *nameOut, int maxNameLength); +extern int CreatePort(int *port); +extern int AcceptConnection(int socket); +extern int Connect(const char *hostname, int port); +extern void CloseSocket(int socket); +extern int SendData(int socket, const void *data, int bytes); +extern int ReceiveData(int socket, void *data, int bytes); +extern int SendString(int socket, const char *str); +extern int ReceiveString(int socket, char *str, int maxLen); + + +#endif /* IPC_H */ diff --git a/progs/xdemos/offset.c b/progs/xdemos/offset.c index 0ad9147aea..6c5abf383b 100644 --- a/progs/xdemos/offset.c +++ b/progs/xdemos/offset.c @@ -47,7 +47,6 @@ PERFORMANCE OF THIS SOFTWARE.  #include <GL/glx.h> -#include <GL/glu.h>  #include <X11/keysym.h>  #include <stdlib.h>  #include <stdio.h> @@ -135,7 +134,7 @@ int main(int argc, char** argv) {      /* set up viewing parameters */      glMatrixMode(GL_PROJECTION); -    gluPerspective(20, 1, 10, 20); +    glFrustum(-1, 1, -1, 1, 6, 20);      glMatrixMode(GL_MODELVIEW);      glTranslatef(0, 0, -15); diff --git a/progs/xdemos/pbutil.c b/progs/xdemos/pbutil.c index d0bbd1b0fc..ce133d012d 100644 --- a/progs/xdemos/pbutil.c +++ b/progs/xdemos/pbutil.c @@ -18,12 +18,12 @@   * Test if we pixel buffers are available for a particular X screen.   * Input:  dpy - the X display   *         screen - screen number - * Return:  0 = pixel buffers not available. - *          1 = pixel buffers are available via GLX 1.3. - *          2 = pixel buffers are available via GLX_SGIX_fbconfig/pbuffer. + * Return:  0 = fbconfigs not available. + *          1 = fbconfigs are available via GLX 1.3. + *          2 = fbconfigs and pbuffers are available via GLX_SGIX_fbconfig   */  int -QueryPbuffers(Display *dpy, int screen) +QueryFBConfig(Display *dpy, int screen)  {  #if defined(GLX_VERSION_1_3)     { @@ -40,36 +40,55 @@ QueryPbuffers(Display *dpy, int screen)     }  #endif -#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)     /* Try the SGIX extensions */     {        char *extensions;        extensions = (char *) glXQueryServerString(dpy, screen, GLX_EXTENSIONS); -      if (!extensions || -          !strstr(extensions,"GLX_SGIX_fbconfig") || -          !strstr(extensions,"GLX_SGIX_pbuffer")) { -         return 0; +      if (extensions && strstr(extensions,"GLX_SGIX_fbconfig")) { +	 return 2;        } -      return 2;     } -#endif     return 0;  } +/** + * Test if we pixel buffers are available for a particular X screen. + * Input:  dpy - the X display + *         screen - screen number + * Return:  0 = pixel buffers not available. + *          1 = pixel buffers are available via GLX 1.3. + *          2 = pixel buffers are available via GLX_SGIX_fbconfig/pbuffer. + */ +int +QueryPbuffers(Display *dpy, int screen) +{ +   int ret; +   ret = QueryFBConfig(dpy, screen); +   if (ret == 2) { +      char *extensions; +      extensions = (char *) glXQueryServerString(dpy, screen, GLX_EXTENSIONS); +      if (extensions && strstr(extensions, "GLX_SGIX_pbuffer")) +	 return 2; +      else +	 return 0; +   } +   else +      return ret; +}  FBCONFIG *  ChooseFBConfig(Display *dpy, int screen, const int attribs[], int *nConfigs)  { -   int pbSupport = QueryPbuffers(dpy, screen); +   int fbcSupport = QueryPbuffers(dpy, screen);  #if defined(GLX_VERSION_1_3) -   if (pbSupport == 1) { +   if (fbcSupport == 1) {        return glXChooseFBConfig(dpy, screen, attribs, nConfigs);     }  #endif  #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer) -   if (pbSupport == 2) { +   if (fbcSupport == 2) {        return glXChooseFBConfigSGIX(dpy, screen, (int *) attribs, nConfigs);     }  #endif @@ -80,14 +99,14 @@ ChooseFBConfig(Display *dpy, int screen, const int attribs[], int *nConfigs)  FBCONFIG *  GetAllFBConfigs(Display *dpy, int screen, int *nConfigs)  { -   int pbSupport = QueryPbuffers(dpy, screen); +   int fbcSupport = QueryFBConfig(dpy, screen);  #if defined(GLX_VERSION_1_3) -   if (pbSupport == 1) { +   if (fbcSupport == 1) {        return glXGetFBConfigs(dpy, screen, nConfigs);     }  #endif  #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer) -   if (pbSupport == 2) { +   if (fbcSupport == 2) {        /* The GLX_SGIX_fbconfig extensions says to pass NULL to get list         * of all available configurations.         */ @@ -101,14 +120,14 @@ GetAllFBConfigs(Display *dpy, int screen, int *nConfigs)  XVisualInfo *  GetVisualFromFBConfig(Display *dpy, int screen, FBCONFIG config)  { -   int pbSupport = QueryPbuffers(dpy, screen); +   int fbcSupport = QueryFBConfig(dpy, screen);  #if defined(GLX_VERSION_1_3) -   if (pbSupport == 1) { +   if (fbcSupport == 1) {        return glXGetVisualFromFBConfig(dpy, config);     }  #endif  #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer) -   if (pbSupport == 2) { +   if (fbcSupport == 2) {        return glXGetVisualFromFBConfigSGIX(dpy, config);     }  #endif @@ -130,11 +149,11 @@ GetFBConfigAttrib(Display *dpy, int screen,                    int attrib                    )  { -   int pbSupport = QueryPbuffers(dpy, screen); +   int fbcSupport = QueryFBConfig(dpy, screen);     int value = 0;  #if defined(GLX_VERSION_1_3) -   if (pbSupport == 1) { +   if (fbcSupport == 1) {        /* ok */        if (glXGetFBConfigAttrib(dpy, config, attrib, &value) != 0) {           value = 0; @@ -145,7 +164,7 @@ GetFBConfigAttrib(Display *dpy, int screen,  #endif  #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer) -   if (pbSupport == 2) { +   if (fbcSupport == 2) {        if (glXGetFBConfigAttribSGIX(dpy, config, attrib, &value) != 0) {           value = 0;        } @@ -295,9 +314,9 @@ PrintFBConfigInfo(Display *dpy, int screen, FBCONFIG config, Bool horizFormat)  GLXContext  CreateContext(Display *dpy, int screen, FBCONFIG config)  { -   int pbSupport = QueryPbuffers(dpy, screen); +   int fbcSupport = QueryFBConfig(dpy, screen);  #if defined(GLX_VERSION_1_3) -   if (pbSupport == 1) { +   if (fbcSupport == 1) {        /* GLX 1.3 */        GLXContext c;        c = glXCreateNewContext(dpy, config, GLX_RGBA_TYPE, NULL, True); @@ -309,7 +328,7 @@ CreateContext(Display *dpy, int screen, FBCONFIG config)     }  #endif  #if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer) -   if (pbSupport == 2) { +   if (fbcSupport == 2) {        GLXContext c;        c = glXCreateContextWithConfigSGIX(dpy, config, GLX_RGBA_TYPE_SGIX, NULL, True);        if (!c) { @@ -393,6 +412,7 @@ CreatePbuffer(Display *dpy, int screen, FBCONFIG config,        pBuffer = None;     } +   XSync(dpy, False);     /* Restore original X error handler */     (void) XSetErrorHandler(oldHandler); diff --git a/progs/xdemos/pbutil.h b/progs/xdemos/pbutil.h index e95b2565a2..d420522ff0 100644 --- a/progs/xdemos/pbutil.h +++ b/progs/xdemos/pbutil.h @@ -27,6 +27,9 @@  extern int +QueryFBConfig(Display *dpy, int screen); + +extern int  QueryPbuffers(Display *dpy, int screen); diff --git a/progs/xdemos/shape.c b/progs/xdemos/shape.c index dbbc0b4ff7..5ff09708be 100644 --- a/progs/xdemos/shape.c +++ b/progs/xdemos/shape.c @@ -34,7 +34,6 @@  static int Width=500, Height=500;  static float Xangle = 0.0, Yangle = 0.0; -static int Redraw = 0;  static int Sides = 5;  static int MinSides = 3;  static int MaxSides = 20; | 
