diff options
Diffstat (limited to 'progs/xdemos')
-rw-r--r-- | progs/xdemos/.gitignore | 2 | ||||
-rw-r--r-- | progs/xdemos/Makefile | 32 | ||||
-rw-r--r-- | progs/xdemos/descrip.mms | 83 | ||||
-rw-r--r-- | progs/xdemos/glsync.c | 2 | ||||
-rw-r--r-- | progs/xdemos/glthreads.c | 285 | ||||
-rw-r--r-- | progs/xdemos/glxcontexts.c | 163 | ||||
-rw-r--r-- | progs/xdemos/glxgears.c | 72 | ||||
-rw-r--r-- | progs/xdemos/glxheads.c | 3 | ||||
-rw-r--r-- | progs/xdemos/glxpixmap.c | 1 | ||||
-rw-r--r-- | progs/xdemos/glxswapcontrol.c | 15 | ||||
-rw-r--r-- | progs/xdemos/manywin.c | 2 | ||||
-rw-r--r-- | progs/xdemos/multictx.c | 585 | ||||
-rw-r--r-- | progs/xdemos/opencloseopen.c | 2 | ||||
-rw-r--r-- | progs/xdemos/overlay.c | 3 | ||||
-rw-r--r-- | progs/xdemos/sharedtex_mt.c | 486 |
15 files changed, 1447 insertions, 289 deletions
diff --git a/progs/xdemos/.gitignore b/progs/xdemos/.gitignore index 084dee5d84..1b9b3a87c0 100644 --- a/progs/xdemos/.gitignore +++ b/progs/xdemos/.gitignore @@ -13,11 +13,13 @@ glxpixmap glxsnoop glxswapcontrol manywin +multictx offset overlay pbdemo pbinfo sharedtex +sharedtex_mt texture_from_pixmap wincopy xdemo diff --git a/progs/xdemos/Makefile b/progs/xdemos/Makefile index f8f2f15380..53e1c54ef3 100644 --- a/progs/xdemos/Makefile +++ b/progs/xdemos/Makefile @@ -26,11 +26,13 @@ PROGS = \ glxsnoop \ glxswapcontrol \ manywin \ + multictx \ offset \ overlay \ pbinfo \ pbdemo \ sharedtex \ + sharedtex_mt \ texture_from_pixmap \ wincopy \ xfont \ @@ -50,7 +52,7 @@ EXTRA_PROGS = \ .SUFFIXES: .c .c: $(LIB_DEP) - $(CC) -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) $(LDFLAGS) $< $(LIBS) -o $@ + $(APP_CC) -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) $(LDFLAGS) $< $(LIBS) -o $@ ##### TARGETS ##### @@ -68,44 +70,44 @@ clean: # special cases pbinfo: pbinfo.o pbutil.o - $(CC) $(CFLAGS) $(LDFLAGS) pbinfo.o pbutil.o $(LIBS) -o $@ + $(APP_CC) $(CFLAGS) $(LDFLAGS) pbinfo.o pbutil.o $(LIBS) -o $@ pbdemo: pbdemo.o pbutil.o - $(CC) $(CFLAGS) $(LDFLAGS) pbdemo.o pbutil.o $(LIBS) -o $@ + $(APP_CC) $(CFLAGS) $(LDFLAGS) pbdemo.o pbutil.o $(LIBS) -o $@ pbinfo.o: pbinfo.c pbutil.h - $(CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) pbinfo.c + $(APP_CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) pbinfo.c pbdemo.o: pbdemo.c pbutil.h - $(CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) pbdemo.c + $(APP_CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) pbdemo.c pbutil.o: pbutil.c pbutil.h - $(CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) pbutil.c + $(APP_CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) pbutil.c glxgears_fbconfig: glxgears_fbconfig.o pbutil.o - $(CC) $(CFLAGS) $(LDFLAGS) glxgears_fbconfig.o pbutil.o $(LIBS) -o $@ + $(APP_CC) $(CFLAGS) $(LDFLAGS) glxgears_fbconfig.o pbutil.o $(LIBS) -o $@ glxgears_fbconfig.o: glxgears_fbconfig.c pbutil.h - $(CC) -I$(INCDIR) $(X11_INCLUDES) $(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 - $(CC) $(CFLAGS) $(LDFLAGS) xrotfontdemo.o xuserotfont.o $(LIBS) -o $@ + $(APP_CC) $(CFLAGS) $(LDFLAGS) xrotfontdemo.o xuserotfont.o $(LIBS) -o $@ xuserotfont.o: xuserotfont.c xuserotfont.h - $(CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) xuserotfont.c + $(APP_CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) xuserotfont.c xrotfontdemo.o: xrotfontdemo.c xuserotfont.h - $(CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) xrotfontdemo.c + $(APP_CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) xrotfontdemo.c corender: corender.o ipc.o - $(CC) $(CFLAGS) corender.o ipc.o $(LIBS) -o $@ + $(APP_CC) $(CFLAGS) $(LDFLAGS) corender.o ipc.o $(LIBS) -o $@ corender.o: corender.c ipc.h - $(CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) corender.c + $(APP_CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) corender.c ipc.o: ipc.c ipc.h - $(CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) ipc.c + $(APP_CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) ipc.c yuvrect_client: yuvrect_client.c - $(CC) -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) $< $(LDFLAGS) $(LIBS) -l$(GLU_LIB) -o $@ + $(APP_CC) -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) $< $(LDFLAGS) $(LIBS) -l$(GLU_LIB) -o $@ diff --git a/progs/xdemos/descrip.mms b/progs/xdemos/descrip.mms deleted file mode 100644 index aa74daff59..0000000000 --- a/progs/xdemos/descrip.mms +++ /dev/null @@ -1,83 +0,0 @@ -# Makefile for GLUT-based demo programs for VMS -# contributed by Jouk Jansen joukj@hrem.stm.tudelft.nl - - -.first - define gl [--.include.gl] - -.include [--]mms-config. - -##### MACROS ##### - -INCDIR = ([--.include],[-.util]) -CFLAGS = /include=$(INCDIR)/prefix=all/name=(as_is,short)/nowarn/float=ieee/ieee=denorm - -.ifdef SHARE -GL_LIBS = $(XLIBS) -.else -GL_LIBS = [--.lib]libGLUT/l,libMesaGLU/l,libMesaGL/l,$(XLIBS) -.endif - -LIB_DEP = [--.lib]$(GL_LIB) [--.lib]$(GLU_LIB) [--.lib]$(GLUT_LIB) - -PROGS =glthreads.exe,\ - glxdemo.exe,\ - glxgears.exe,\ - glxheads.exe,\ - glxinfo.exe,\ - glxpixmap.exe,\ - manywin.exe,\ - offset.exe,\ - pbinfo.exe,\ - pbdemo.exe,\ - wincopy.exe,\ - xdemo.exe,\ - xfont.exe - -##### RULES ##### -.obj.exe : - cxxlink $(MMS$TARGET_NAME),$(GL_LIBS) - -##### TARGETS ##### -default : - $(MMS)$(MMSQUALIFIERS) $(PROGS) - -clean : - delete *.obj;* - -realclean : - delete $(PROGS) - delete *.obj;* - - -glthreads.exe : glthreads.obj $(LIB_DEP) -glxdemo.exe : glxdemo.obj $(LIB_DEP) -glxgears.exe : glxgears.obj $(LIB_DEP) -glxheads.exe : glxheads.obj $(LIB_DEP) -glxinfo.exe : glxinfo.obj $(LIB_DEP) -glxpixmap.exe : glxpixmap.obj $(LIB_DEP) -manywin.exe : manywin.obj $(LIB_DEP) -offset.exe : offset.obj $(LIB_DEP) -pbinfo.exe : pbinfo.obj pbutil.obj $(LIB_DEP) - cxxlink pbinfo.obj,pbutil.obj,$(GL_LIBS) -pbdemo.exe : pbdemo.obj pbutil.obj $(LIB_DEP) - cxxlink pbdemo.obj,pbutil.obj,$(GL_LIBS) -wincopy.exe : wincopy.obj $(LIB_DEP) -xdemo.exe : xdemo.obj $(LIB_DEP) -xfont.exe :xfont.obj $(LIB_DEP) - - -glthreads.obj : glthreads.c -glxdemo.obj : glxdemo.c -glxgears.obj : glxgears.c -glxheads.obj : glxheads.c -glxinfo.obj : glxinfo.c -glxpixmap.obj : glxpixmap.c -manywin.obj : manywin.c -offset.obj : offset.c -pbinfo.obj : pbinfo.c -pbutil.obj : pbutil.c -pbdemo.obj : pbdemo.c -wincopy.obj : wincopy.c -xdemo.obj : xdemo.c -xfont.obj :xfont.c diff --git a/progs/xdemos/glsync.c b/progs/xdemos/glsync.c index 95cd1af400..34167d339f 100644 --- a/progs/xdemos/glsync.c +++ b/progs/xdemos/glsync.c @@ -112,6 +112,7 @@ int main(int argc, char *argv[]) int attrib[14]; GLint last_val = -1, count = 0; Window winGL; + GLXContext context; int dummy; Atom wmDelete; enum sync_type waitforsync = none; @@ -185,7 +186,6 @@ int main(int argc, char *argv[]) attrib[10] = None; } - GLXContext context; pvi = glXChooseVisual(disp, DefaultScreen(disp), attrib); if (!pvi) { fprintf(stderr, "failed to choose visual, exiting\n"); diff --git a/progs/xdemos/glthreads.c b/progs/xdemos/glthreads.c index 4f87ee75d4..ea5474870b 100644 --- a/progs/xdemos/glthreads.c +++ b/progs/xdemos/glthreads.c @@ -26,17 +26,31 @@ * -p Open a display connection for each thread * -l Enable application-side locking * -n <num threads> Number of threads to create (default is 2) - * -display <display name> Specify X display (default is :0.0) + * -display <display name> Specify X display (default is $DISPLAY) + * -t Use texture mapping * * Brian Paul 20 July 2000 */ +/* + * Notes: + * - Each thread gets its own GLX context. + * + * - The GLX contexts share texture objects. + * + * - When 't' is pressed to update the texture image, the window/thread which + * has input focus is signalled to change the texture. The other threads + * should see the updated texture the next time they call glBindTexture. + */ + + #if defined(PTHREADS) /* defined by Mesa on Linux and other platforms */ #include <assert.h> #include <GL/gl.h> #include <GL/glx.h> +#include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -56,6 +70,8 @@ struct winthread { float Angle; int WinWidth, WinHeight; GLboolean NewSize; + GLboolean Initialized; + GLboolean MakeNewTexture; }; @@ -66,8 +82,13 @@ static volatile GLboolean ExitFlag = GL_FALSE; static GLboolean MultiDisplays = 0; static GLboolean Locking = 0; +static GLboolean Texture = GL_FALSE; +static GLuint TexObj = 12; +static GLboolean Animate = GL_TRUE; static pthread_mutex_t Mutex; +static pthread_cond_t CondVar; +static pthread_mutex_t CondMutex; static void @@ -78,6 +99,59 @@ Error(const char *msg) } +static void +signal_redraw(void) +{ + pthread_mutex_lock(&CondMutex); + pthread_cond_broadcast(&CondVar); + pthread_mutex_unlock(&CondMutex); +} + + +static void +MakeNewTexture(struct winthread *wt) +{ +#define TEX_SIZE 128 + static float step = 0.0; + GLfloat image[TEX_SIZE][TEX_SIZE][4]; + GLint width; + int i, j; + + for (j = 0; j < TEX_SIZE; j++) { + for (i = 0; i < TEX_SIZE; i++) { + float dt = 5.0 * (j - 0.5 * TEX_SIZE) / TEX_SIZE; + float ds = 5.0 * (i - 0.5 * TEX_SIZE) / TEX_SIZE; + float r = dt * dt + ds * ds + step; + image[j][i][0] = + image[j][i][1] = + image[j][i][2] = 0.75 + 0.25 * cos(r); + image[j][i][3] = 1.0; + } + } + + step += 0.5; + + glBindTexture(GL_TEXTURE_2D, TexObj); + + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width); + if (width) { + assert(width == TEX_SIZE); + /* sub-tex replace */ + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TEX_SIZE, TEX_SIZE, + GL_RGBA, GL_FLOAT, image); + } + else { + /* create new */ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEX_SIZE, TEX_SIZE, 0, + GL_RGBA, GL_FLOAT, image); + } +} + + + /* draw a colored cube */ static void draw_object(void) @@ -86,52 +160,61 @@ draw_object(void) glScalef(0.75, 0.75, 0.75); glColor3f(1, 0, 0); - glBegin(GL_POLYGON); - glVertex3f(1, -1, -1); - glVertex3f(1, 1, -1); - glVertex3f(1, 1, 1); - glVertex3f(1, -1, 1); - glEnd(); + if (Texture) { + glBindTexture(GL_TEXTURE_2D, TexObj); + glEnable(GL_TEXTURE_2D); + } + else { + glDisable(GL_TEXTURE_2D); + } + + glBegin(GL_QUADS); + + /* -X */ glColor3f(0, 1, 1); - glBegin(GL_POLYGON); - glVertex3f(-1, -1, -1); - glVertex3f(-1, 1, -1); - glVertex3f(-1, 1, 1); - glVertex3f(-1, -1, 1); - glEnd(); + glTexCoord2f(0, 0); glVertex3f(-1, -1, -1); + glTexCoord2f(1, 0); glVertex3f(-1, 1, -1); + glTexCoord2f(1, 1); glVertex3f(-1, 1, 1); + glTexCoord2f(0, 1); glVertex3f(-1, -1, 1); - glColor3f(0, 1, 0); - glBegin(GL_POLYGON); - glVertex3f(-1, 1, -1); - glVertex3f( 1, 1, -1); - glVertex3f( 1, 1, 1); - glVertex3f(-1, 1, 1); - glEnd(); + /* +X */ + glColor3f(1, 0, 0); + glTexCoord2f(0, 0); glVertex3f(1, -1, -1); + glTexCoord2f(1, 0); glVertex3f(1, 1, -1); + glTexCoord2f(1, 1); glVertex3f(1, 1, 1); + glTexCoord2f(0, 1); glVertex3f(1, -1, 1); + /* -Y */ glColor3f(1, 0, 1); - glBegin(GL_POLYGON); - glVertex3f(-1, -1, -1); - glVertex3f( 1, -1, -1); - glVertex3f( 1, -1, 1); - glVertex3f(-1, -1, 1); - glEnd(); + glTexCoord2f(0, 0); glVertex3f(-1, -1, -1); + glTexCoord2f(1, 0); glVertex3f( 1, -1, -1); + glTexCoord2f(1, 1); glVertex3f( 1, -1, 1); + glTexCoord2f(0, 1); glVertex3f(-1, -1, 1); - glColor3f(0, 0, 1); - glBegin(GL_POLYGON); - glVertex3f(-1, -1, 1); - glVertex3f( 1, -1, 1); - glVertex3f( 1, 1, 1); - glVertex3f(-1, 1, 1); - glEnd(); + /* +Y */ + glColor3f(0, 1, 0); + glTexCoord2f(0, 0); glVertex3f(-1, 1, -1); + glTexCoord2f(1, 0); glVertex3f( 1, 1, -1); + glTexCoord2f(1, 1); glVertex3f( 1, 1, 1); + glTexCoord2f(0, 1); glVertex3f(-1, 1, 1); + /* -Z */ glColor3f(1, 1, 0); - glBegin(GL_POLYGON); - glVertex3f(-1, -1, -1); - glVertex3f( 1, -1, -1); - glVertex3f( 1, 1, -1); - glVertex3f(-1, 1, -1); + glTexCoord2f(0, 0); glVertex3f(-1, -1, -1); + glTexCoord2f(1, 0); glVertex3f( 1, -1, -1); + glTexCoord2f(1, 1); glVertex3f( 1, 1, -1); + glTexCoord2f(0, 1); glVertex3f(-1, 1, -1); + + /* +Y */ + glColor3f(0, 0, 1); + glTexCoord2f(0, 0); glVertex3f(-1, -1, 1); + glTexCoord2f(1, 0); glVertex3f( 1, -1, 1); + glTexCoord2f(1, 1); glVertex3f( 1, 1, 1); + glTexCoord2f(0, 1); glVertex3f(-1, 1, 1); + glEnd(); + glPopMatrix(); } @@ -143,6 +226,8 @@ resize(struct winthread *wt, int w, int h) wt->NewSize = GL_TRUE; wt->WinWidth = w; wt->WinHeight = h; + if (!Animate) + signal_redraw(); } @@ -152,18 +237,19 @@ resize(struct winthread *wt, int w, int h) static void draw_loop(struct winthread *wt) { - GLboolean firstIter = GL_TRUE; - while (!ExitFlag) { if (Locking) pthread_mutex_lock(&Mutex); glXMakeCurrent(wt->Dpy, wt->Win, wt->Context); - if (firstIter) { + if (!wt->Initialized) { printf("glthreads: %d: GL_RENDERER = %s\n", wt->Index, (char *) glGetString(GL_RENDERER)); - firstIter = GL_FALSE; + if (Texture /*&& wt->Index == 0*/) { + MakeNewTexture(wt); + } + wt->Initialized = GL_TRUE; } if (Locking) @@ -183,10 +269,15 @@ draw_loop(struct winthread *wt) wt->NewSize = GL_FALSE; } + if (wt->MakeNewTexture) { + MakeNewTexture(wt); + wt->MakeNewTexture = GL_FALSE; + } + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); - glRotatef(wt->Angle, 0, 0, 1); + glRotatef(wt->Angle, 0, 1, 0); glRotatef(wt->Angle, 1, 0, 0); glScalef(0.7, 0.7, 0.7); draw_object(); @@ -200,12 +291,63 @@ draw_loop(struct winthread *wt) if (Locking) pthread_mutex_unlock(&Mutex); - usleep(5000); + if (Animate) { + usleep(5000); + } + else { + /* wait for signal to draw */ + pthread_mutex_lock(&CondMutex); + pthread_cond_wait(&CondVar, &CondMutex); + pthread_mutex_unlock(&CondMutex); + } wt->Angle += 1.0; } } +static void +keypress(XEvent *event, struct winthread *wt) +{ + char buf[100]; + KeySym keySym; + XComposeStatus stat; + + XLookupString(&event->xkey, buf, sizeof(buf), &keySym, &stat); + + switch (keySym) { + case XK_Escape: + /* tell all threads to exit */ + if (!Animate) { + signal_redraw(); + } + ExitFlag = GL_TRUE; + /*printf("exit draw_loop %d\n", wt->Index);*/ + return; + case XK_t: + case XK_T: + if (Texture) { + wt->MakeNewTexture = GL_TRUE; + if (!Animate) + signal_redraw(); + } + break; + case XK_a: + case XK_A: + Animate = !Animate; + if (Animate) /* yes, prev Animate state! */ + signal_redraw(); + break; + case XK_s: + case XK_S: + if (!Animate) + signal_redraw(); + break; + default: + ; /* nop */ + } +} + + /* * The main process thread runs this loop. * Single display connection for all threads. @@ -251,10 +393,14 @@ event_loop(Display *dpy) } break; case KeyPress: - /* tell all threads to exit */ - ExitFlag = GL_TRUE; - /*printf("exit draw_loop %d\n", wt->Index);*/ - return; + for (i = 0; i < NumWinThreads; i++) { + struct winthread *wt = &WinThreads[i]; + if (event.xkey.window == wt->Win) { + keypress(&event, wt); + break; + } + } + break; default: /*no-op*/ ; } @@ -282,12 +428,10 @@ event_loop_multi(void) resize(wt, event.xconfigure.width, event.xconfigure.height); break; case KeyPress: - /* tell all threads to exit */ - ExitFlag = GL_TRUE; - /*printf("exit draw_loop %d\n", wt->Index);*/ - return; + keypress(&event, wt); + break; default: - /*no-op*/ ; + ; /* nop */ } } w = (w + 1) % NumWinThreads; @@ -301,7 +445,7 @@ event_loop_multi(void) * we'll call this once for each thread, before the threads are created. */ static void -create_window(struct winthread *wt) +create_window(struct winthread *wt, GLXContext shareCtx) { Window win; GLXContext ctx; @@ -317,9 +461,9 @@ create_window(struct winthread *wt) unsigned long mask; Window root; XVisualInfo *visinfo; - int width = 80, height = 80; - int xpos = (wt->Index % 10) * 90; - int ypos = (wt->Index / 10) * 100; + int width = 160, height = 160; + int xpos = (wt->Index % 8) * (width + 10); + int ypos = (wt->Index / 8) * (width + 20); scrnum = DefaultScreen(wt->Dpy); root = RootWindow(wt->Dpy, scrnum); @@ -356,7 +500,7 @@ create_window(struct winthread *wt) } - ctx = glXCreateContext(wt->Dpy, visinfo, NULL, True); + ctx = glXCreateContext(wt->Dpy, visinfo, shareCtx, True); if (!ctx) { Error("Couldn't create GLX context"); } @@ -417,13 +561,19 @@ usage(void) printf(" -n NUMTHREADS Number of threads to create\n"); printf(" -p Use a separate display connection for each thread\n"); printf(" -l Use application-side locking\n"); + printf(" -t Enable texturing\n"); + printf("Keyboard:\n"); + printf(" Esc Exit\n"); + printf(" t Change texture image (requires -t option)\n"); + printf(" a Toggle animation\n"); + printf(" s Step rotation (when not animating)\n"); } int main(int argc, char *argv[]) { - char *displayName = ":0.0"; + char *displayName = NULL; int numThreads = 2; Display *dpy = NULL; int i; @@ -445,6 +595,9 @@ main(int argc, char *argv[]) else if (strcmp(argv[i], "-l") == 0) { Locking = 1; } + else if (strcmp(argv[i], "-t") == 0) { + Texture = 1; + } else if (strcmp(argv[i], "-n") == 0 && i + 1 < argc) { numThreads = atoi(argv[i + 1]); if (numThreads < 1) @@ -491,9 +644,9 @@ main(int argc, char *argv[]) } } - if (Locking) { - pthread_mutex_init(&Mutex, NULL); - } + pthread_mutex_init(&Mutex, NULL); + pthread_mutex_init(&CondMutex, NULL); + pthread_cond_init(&CondVar, NULL); printf("glthreads: creating windows\n"); @@ -501,6 +654,8 @@ main(int argc, char *argv[]) /* Create the GLX windows and contexts */ for (i = 0; i < numThreads; i++) { + GLXContext share; + if (MultiDisplays) { WinThreads[i].Dpy = XOpenDisplay(displayName); assert(WinThreads[i].Dpy); @@ -509,7 +664,11 @@ main(int argc, char *argv[]) WinThreads[i].Dpy = dpy; } WinThreads[i].Index = i; - create_window(&WinThreads[i]); + WinThreads[i].Initialized = GL_FALSE; + + share = (Texture && i > 0) ? WinThreads[0].Context : 0; + + create_window(&WinThreads[i], share); } printf("glthreads: creating threads\n"); diff --git a/progs/xdemos/glxcontexts.c b/progs/xdemos/glxcontexts.c index a9ff326ed5..9f83679acd 100644 --- a/progs/xdemos/glxcontexts.c +++ b/progs/xdemos/glxcontexts.c @@ -20,16 +20,17 @@ */ /* - * This is a port of the infamous "gears" demo to straight GLX (i.e. no GLUT) - * Port by Brian Paul 23 March 2001 + * Version of glxgears that creates/destroys the rendering context for each + * frame. Also periodically destroy/recreate the window. + * Good for finding memory leaks, etc. * * Command line options: * -info print GL implementation information - * -stereo use stereo enabled GLX visual * */ +#include <assert.h> #include <math.h> #include <stdlib.h> #include <stdio.h> @@ -92,13 +93,8 @@ static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0; static GLint gear1, gear2, gear3; static GLfloat angle = 0.0; -static GLboolean fullscreen = GL_FALSE; /* Create a single fullscreen window */ -static GLboolean stereo = GL_FALSE; /* Enable stereo. */ -static GLfloat eyesep = 5.0; /* Eye separation. */ -static GLfloat fix_point = 40.0; /* Fixation point distance. */ -static GLfloat left, right, asp; /* Stereo frustum params. */ - - XVisualInfo *visinfo; +static XVisualInfo *visinfo = NULL; +static int WinWidth = 300, WinHeight = 300; /* @@ -272,22 +268,13 @@ do_draw(void) } - /* new window size or exposure */ static void reshape(int width, int height) { glViewport(0, 0, (GLint) width, (GLint) height); - if (stereo) { - GLfloat w; - - asp = (GLfloat) height / (GLfloat) width; - w = fix_point * (1.0 / 5.0); - - left = -5.0 * ((w - 0.5 * eyesep) / fix_point); - right = 5.0 * ((w + 0.5 * eyesep) / fix_point); - } else { + { GLfloat h = (GLfloat) height / (GLfloat) width; glMatrixMode(GL_PROJECTION); @@ -299,7 +286,6 @@ reshape(int width, int height) glLoadIdentity(); glTranslatef(0.0, 0.0, -40.0); } - static void @@ -337,7 +323,7 @@ init(void) glEnable(GL_NORMALIZE); } - + static void draw( Display *dpy, Window win ) @@ -354,36 +340,13 @@ draw( Display *dpy, Window win ) init(); - if (stereo) { - /* First left eye. */ - glDrawBuffer(GL_BACK_LEFT); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glFrustum(left, right, -asp, asp, 5.0, 60.0); - - glMatrixMode(GL_MODELVIEW); + reshape(WinWidth, WinHeight); - glPushMatrix(); - glTranslated(+0.5 * eyesep, 0.0, 0.0); - do_draw(); - glPopMatrix(); + do_draw(); - /* Then right eye. */ - glDrawBuffer(GL_BACK_RIGHT); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glFrustum(-right, -left, -asp, asp, 5.0, 60.0); - - glMatrixMode(GL_MODELVIEW); - - glPushMatrix(); - glTranslated(-0.5 * eyesep, 0.0, 0.0); - do_draw(); - glPopMatrix(); - } else - do_draw(); + glDeleteLists(gear1, 1); + glDeleteLists(gear2, 1); + glDeleteLists(gear3, 1); glXSwapBuffers(dpy, win); glXDestroyContext(dpy, ctx); @@ -406,14 +369,6 @@ make_window( Display *dpy, const char *name, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 1, None }; - int stereoAttribs[] = { GLX_RGBA, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - GLX_DOUBLEBUFFER, - GLX_DEPTH_SIZE, 1, - GLX_STEREO, - None }; int scrnum; XSetWindowAttributes attr; unsigned long mask; @@ -423,22 +378,12 @@ make_window( Display *dpy, const char *name, scrnum = DefaultScreen( dpy ); root = RootWindow( dpy, scrnum ); - if (fullscreen) { - x = 0; y = 0; - width = DisplayWidth( dpy, scrnum ); - height = DisplayHeight( dpy, scrnum ); - } + if (visinfo) + XFree(visinfo); - if (stereo) - visinfo = glXChooseVisual( dpy, scrnum, stereoAttribs ); - else - visinfo = glXChooseVisual( dpy, scrnum, attribs ); + visinfo = glXChooseVisual( dpy, scrnum, attribs ); if (!visinfo) { - if (stereo) { - printf("Error: couldn't get an RGB, " - "Double-buffered, Stereo visual\n"); - } else - printf("Error: couldn't get an RGB, Double-buffered visual\n"); + printf("Error: couldn't get an RGB, Double-buffered visual\n"); exit(1); } @@ -447,7 +392,7 @@ make_window( Display *dpy, const char *name, attr.border_pixel = 0; attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone); attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; - attr.override_redirect = fullscreen; + attr.override_redirect = 0; mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect; win = XCreateWindow( dpy, root, x, y, width, height, @@ -475,10 +420,9 @@ static void event_loop(Display *dpy) { Window win; - make_window(dpy, "glxgears", 0, 0, 300, 300, &win); + make_window(dpy, "glxgears", 0, 0, WinWidth, WinHeight, &win); XMapWindow(dpy, win); - while (1) { while (XPending(dpy) > 0) { XEvent event; @@ -488,34 +432,35 @@ event_loop(Display *dpy) /* we'll redraw below */ break; case ConfigureNotify: - reshape(event.xconfigure.width, event.xconfigure.height); + WinWidth = event.xconfigure.width; + WinHeight = 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; - } - } - } + { + 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; + } + } + } } } @@ -546,9 +491,12 @@ event_loop(Display *dpy) printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds, fps); tRate0 = t; - + + /* Destroy window and create new one */ XDestroyWindow(dpy, win); - make_window(dpy, "glxgears", (int)(fps * 100) % 100, (int)(fps * 100) % 100, 300, 300, &win); + make_window(dpy, "glxgears", + (int)(fps * 100) % 100, (int)(fps * 100) % 100, /* x,y */ + WinWidth, WinHeight, &win); XMapWindow(dpy, win); frames = 0; @@ -558,7 +506,6 @@ event_loop(Display *dpy) } - int main(int argc, char *argv[]) { @@ -575,12 +522,6 @@ main(int argc, char *argv[]) else if (strcmp(argv[i], "-info") == 0) { printInfo = GL_TRUE; } - else if (strcmp(argv[i], "-stereo") == 0) { - stereo = GL_TRUE; - } - else if (strcmp(argv[i], "-fullscreen") == 0) { - fullscreen = GL_TRUE; - } else printf("Warrning: unknown parameter: %s\n", argv[i]); } @@ -592,7 +533,6 @@ main(int argc, char *argv[]) return -1; } - if (printInfo) { printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION)); @@ -600,7 +540,6 @@ main(int argc, char *argv[]) printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS)); } - event_loop(dpy); XCloseDisplay(dpy); diff --git a/progs/xdemos/glxgears.c b/progs/xdemos/glxgears.c index 8db717f1aa..088f25a357 100644 --- a/progs/xdemos/glxgears.c +++ b/progs/xdemos/glxgears.c @@ -23,10 +23,7 @@ * This is a port of the infamous "gears" demo to straight GLX (i.e. no GLUT) * Port by Brian Paul 23 March 2001 * - * Command line options: - * -info print GL implementation information - * -stereo use stereo enabled GLX visual - * + * See usage() below for command line options. */ @@ -39,6 +36,11 @@ #include <GL/gl.h> #include <GL/glx.h> +#ifndef GLX_MESA_swap_control +#define GLX_MESA_swap_control 1 +typedef int (*PFNGLXGETSWAPINTERVALMESAPROC)(void); +#endif + #define BENCHMARK @@ -561,12 +563,73 @@ make_window( Display *dpy, const char *name, /** + * Determine whether or not a GLX extension is supported. + */ +static int +is_glx_extension_supported(Display *dpy, const char *query) +{ + const int scrnum = DefaultScreen(dpy); + const char *glx_extensions = NULL; + const size_t len = strlen(query); + const char *ptr; + + if (glx_extensions == NULL) { + glx_extensions = glXQueryExtensionsString(dpy, scrnum); + } + + ptr = strstr(glx_extensions, query); + return ((ptr != NULL) && ((ptr[len] == ' ') || (ptr[len] == '\0'))); +} + + +/** + * Attempt to determine whether or not the display is synched to vblank. + */ +static void +query_vsync(Display *dpy) +{ + int interval = 0; + + + if (is_glx_extension_supported(dpy, "GLX_MESA_swap_control")) { + PFNGLXGETSWAPINTERVALMESAPROC pglXGetSwapIntervalMESA = + (PFNGLXGETSWAPINTERVALMESAPROC) + glXGetProcAddressARB((const GLubyte *) "glXGetSwapIntervalMESA"); + + interval = (*pglXGetSwapIntervalMESA)(); + } else if (is_glx_extension_supported(dpy, "GLX_SGI_swap_control")) { + /* The default swap interval with this extension is 1. Assume that it + * is set to the default. + * + * Many Mesa-based drivers default to 0, but all of these drivers also + * export GLX_MESA_swap_control. In that case, this branch will never + * be taken, and the correct result should be reported. + */ + interval = 1; + } + + + if (interval > 0) { + printf("Running synchronized to the vertical refresh. The framerate should be\n"); + if (interval == 1) { + printf("approximately the same as the monitor refresh rate.\n"); + } else if (interval > 1) { + printf("approximately 1/%d the monitor refresh rate.\n", + interval); + } + } +} + +/** * Handle one X event. * \return NOP, EXIT or DRAW */ static int handle_event(Display *dpy, Window win, XEvent *event) { + (void) dpy; + (void) win; + switch (event->type) { case Expose: return DRAW; @@ -686,6 +749,7 @@ main(int argc, char *argv[]) make_window(dpy, "glxgears", x, y, winWidth, winHeight, &win, &ctx); XMapWindow(dpy, win); glXMakeCurrent(dpy, win, ctx); + query_vsync(dpy); if (printInfo) { printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); diff --git a/progs/xdemos/glxheads.c b/progs/xdemos/glxheads.c index b3290e90d5..b1a63d3d50 100644 --- a/progs/xdemos/glxheads.c +++ b/progs/xdemos/glxheads.c @@ -267,7 +267,8 @@ main(int argc, char *argv[]) printf(" glxheads xdisplayname ...\n"); printf("Example:\n"); printf(" glxheads :0 mars:0 venus:1\n"); - h = AddHead(":0"); + + h = AddHead(XDisplayName(NULL)); if (h) PrintInfo(h); } diff --git a/progs/xdemos/glxpixmap.c b/progs/xdemos/glxpixmap.c index 9db4df2c8b..e1abd22cee 100644 --- a/progs/xdemos/glxpixmap.c +++ b/progs/xdemos/glxpixmap.c @@ -178,6 +178,7 @@ int main( int argc, char *argv[] ) glColor3f( 0.0, 1.0, 1.0 ); glRectf( -0.75, -0.75, 0.75, 0.75 ); glFlush(); + glXWaitGL(); XMapWindow( dpy, win ); diff --git a/progs/xdemos/glxswapcontrol.c b/progs/xdemos/glxswapcontrol.c index 2c51801989..cd60d460a0 100644 --- a/progs/xdemos/glxswapcontrol.c +++ b/progs/xdemos/glxswapcontrol.c @@ -303,13 +303,13 @@ draw(void) glDisable(GL_LIGHTING); glShadeModel(GL_SMOOTH); - glEnable( GL_VERTEX_ARRAY ); - glEnable( GL_COLOR_ARRAY ); + glEnableClientState( GL_VERTEX_ARRAY ); + glEnableClientState( GL_COLOR_ARRAY ); glVertexPointer( 3, GL_FLOAT, 0, vert ); glColorPointer( 3, GL_FLOAT, 0, col ); glDrawArrays( GL_POLYGON, 0, 4 ); - glDisable( GL_COLOR_ARRAY ); - glDisable( GL_VERTEX_ARRAY ); + glDisableClientState( GL_COLOR_ARRAY ); + glDisableClientState( GL_VERTEX_ARRAY ); glMatrixMode(GL_PROJECTION); glLoadIdentity(); @@ -587,6 +587,9 @@ event_loop(Display *dpy, Window win) angle += 2.0; draw(); + + glXSwapBuffers(dpy, win); + if ( get_frame_usage != NULL ) { GLfloat temp; @@ -594,8 +597,6 @@ event_loop(Display *dpy, Window win) frame_usage += temp; } - glXSwapBuffers(dpy, win); - /* calc framerate */ { static int t0 = -1; @@ -759,7 +760,7 @@ main(int argc, char *argv[]) Display *dpy; Window win; GLXContext ctx; - char *dpyName = ":0"; + char *dpyName = NULL; int swap_interval = 1; GLboolean do_swap_interval = GL_FALSE; GLboolean force_get_rate = GL_FALSE; diff --git a/progs/xdemos/manywin.c b/progs/xdemos/manywin.c index cfea555210..ee357f32a4 100644 --- a/progs/xdemos/manywin.c +++ b/progs/xdemos/manywin.c @@ -286,7 +286,7 @@ EventLoop(void) XLookupString(&event.xkey, buf, sizeof(buf), &keySym, &stat); switch (keySym) { case XK_Escape: - exit(0); + return; break; case XK_d: case XK_D: diff --git a/progs/xdemos/multictx.c b/progs/xdemos/multictx.c new file mode 100644 index 0000000000..75255b2860 --- /dev/null +++ b/progs/xdemos/multictx.c @@ -0,0 +1,585 @@ +/* + * Copyright (C) 2009 VMware, 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. + */ + +/* + * Test rendering with two contexts into one window. + * Setup different rendering state for each context to check that + * context switching is handled properly. + * + * Brian Paul + * 6 Aug 2009 + */ + + +#include <math.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <sys/time.h> +#include <unistd.h> +#include <X11/Xlib.h> +#include <X11/keysym.h> +#include <GL/gl.h> +#include <GL/glx.h> + + + +#ifndef M_PI +#define M_PI 3.14159265 +#endif + + +/** Event handler results: */ +#define NOP 0 +#define EXIT 1 +#define DRAW 2 + +static GLfloat view_rotx = 0.0, view_roty = 210.0, view_rotz = 0.0; +static GLint gear1, gear2; +static GLfloat angle = 0.0; + +static GLboolean animate = GL_TRUE; /* Animation */ + + +static double +current_time(void) +{ + struct timeval tv; +#ifdef __VMS + (void) gettimeofday(&tv, NULL ); +#else + struct timezone tz; + (void) gettimeofday(&tv, &tz); +#endif + return (double) tv.tv_sec + tv.tv_usec / 1000000.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(int ctx) +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix(); + glRotatef(view_rotx, 1.0, 0.0, 0.0); + glRotatef(view_roty + angle, 0.0, 1.0, 0.0); + glRotatef(view_rotz, 0.0, 0.0, 1.0); + + if (ctx == 0) { + glDisable(GL_CULL_FACE); + glPushMatrix(); + glRotatef(angle, 0.0, 0.0, 1.0); + glCallList(gear1); + glPopMatrix(); + /* This should not effect the other context's rendering */ + glEnable(GL_CULL_FACE); + glCullFace(GL_FRONT_AND_BACK); + } + else { + glPushMatrix(); + glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0); + glCallList(gear2); + glPopMatrix(); + } + + glPopMatrix(); + + /* this flush is important since we'll be switching contexts next */ + glFlush(); +} + + + +static void +draw_frame(Display *dpy, Window win, GLXContext ctx1, GLXContext ctx2) +{ + static double tRot0 = -1.0; + double dt, t = current_time(); + + if (tRot0 < 0.0) + tRot0 = t; + dt = t - tRot0; + tRot0 = t; + + if (animate) { + /* advance rotation for next frame */ + angle += 70.0 * dt; /* 70 degrees per second */ + if (angle > 3600.0) + angle -= 3600.0; + } + + glXMakeCurrent(dpy, (GLXDrawable) win, ctx1); + draw(0); + + glXMakeCurrent(dpy, (GLXDrawable) win, ctx2); + draw(1); + + glXSwapBuffers(dpy, win); +} + + +/* new window size or exposure */ +static void +reshape(Display *dpy, Window win, + GLXContext ctx1, GLXContext ctx2, int width, int height) +{ + int i; + + width /= 2; + + /* loop: left half of window, right half of window */ + for (i = 0; i < 2; i++) { + if (i == 0) + glXMakeCurrent(dpy, win, ctx1); + else + glXMakeCurrent(dpy, win, ctx2); + + glViewport(width * i, 0, width, height); + glScissor(width * i, 0, width, height); + + { + GLfloat h = (GLfloat) height / (GLfloat) width; + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0); + } + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.0, 0.0, -30.0); + } +} + + + +static void +init(Display *dpy, Window win, GLXContext ctx1, GLXContext ctx2) +{ + 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, 0.5 }; + /*static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };*/ + + /* first ctx */ + { + static GLuint stipple[32] = { + 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, + 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, + + 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, + 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, + + 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, + 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, + + 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, + 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00 + }; + + glXMakeCurrent(dpy, win, ctx1); + + glLightfv(GL_LIGHT0, GL_POSITION, pos); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); + + 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(); + + glEnable(GL_NORMALIZE); + glEnable(GL_SCISSOR_TEST); + glClearColor(0.4, 0.4, 0.4, 1.0); + + glPolygonStipple((GLubyte *) stipple); + glEnable(GL_POLYGON_STIPPLE); + } + + /* second ctx */ + { + glXMakeCurrent(dpy, win, ctx2); + + glLightfv(GL_LIGHT0, GL_POSITION, pos); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); + + gear2 = glGenLists(1); + glNewList(gear2, GL_COMPILE); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green); + gear(1.5, 3.0, 1.5, 16, 0.7); + glEndList(); + + glEnable(GL_NORMALIZE); + glEnable(GL_SCISSOR_TEST); + glClearColor(0.6, 0.6, 0.6, 1.0); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } +} + + +/** + * Create an RGB, double-buffered window. + * Return the window and two context handles. + */ +static void +make_window_and_contexts( Display *dpy, const char *name, + int x, int y, int width, int height, + Window *winRet, + GLXContext *ctxRet1, + GLXContext *ctxRet2) +{ + 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; + XSetWindowAttributes attr; + unsigned long mask; + Window root; + Window win; + XVisualInfo *visinfo; + + scrnum = DefaultScreen( dpy ); + root = RootWindow( dpy, scrnum ); + + visinfo = glXChooseVisual( dpy, scrnum, attribs ); + if (!visinfo) { + printf("Error: couldn't get an RGB, Double-buffered visual\n"); + exit(1); + } + + /* 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); + } + + *winRet = win; + *ctxRet1 = glXCreateContext( dpy, visinfo, NULL, True ); + *ctxRet2 = glXCreateContext( dpy, visinfo, NULL, True ); + + if (!*ctxRet1 || !*ctxRet2) { + printf("Error: glXCreateContext failed\n"); + exit(1); + } + + XFree(visinfo); +} + + +/** + * Handle one X event. + * \return NOP, EXIT or DRAW + */ +static int +handle_event(Display *dpy, Window win, GLXContext ctx1, GLXContext ctx2, + XEvent *event) +{ + (void) dpy; + (void) win; + + switch (event->type) { + case Expose: + return DRAW; + case ConfigureNotify: + reshape(dpy, win, ctx1, ctx2, + 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 EXIT; + } + else if (buffer[0] == 'a' || buffer[0] == 'A') { + animate = !animate; + } + } + return DRAW; + } + } + return NOP; +} + + +static void +event_loop(Display *dpy, Window win, GLXContext ctx1, GLXContext ctx2) +{ + while (1) { + int op; + while (!animate || XPending(dpy) > 0) { + XEvent event; + XNextEvent(dpy, &event); + op = handle_event(dpy, win, ctx1, ctx2, &event); + if (op == EXIT) + return; + else if (op == DRAW) + break; + } + + draw_frame(dpy, win, ctx1, ctx2); + } +} + + +int +main(int argc, char *argv[]) +{ + unsigned int winWidth = 800, winHeight = 400; + int x = 0, y = 0; + Display *dpy; + Window win; + GLXContext ctx1, ctx2; + char *dpyName = NULL; + GLboolean printInfo = GL_FALSE; + int i; + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-display") == 0) { + dpyName = argv[i+1]; + i++; + } + else { + return 1; + } + } + + dpy = XOpenDisplay(dpyName); + if (!dpy) { + printf("Error: couldn't open display %s\n", + dpyName ? dpyName : getenv("DISPLAY")); + return -1; + } + + make_window_and_contexts(dpy, "multictx", x, y, winWidth, winHeight, + &win, &ctx1, &ctx2); + XMapWindow(dpy, win); + + 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(dpy, win, ctx1, ctx2); + + /* Set initial projection/viewing transformation. + * We can't be sure we'll get a ConfigureNotify event when the window + * first appears. + */ + reshape(dpy, win, ctx1, ctx2, winWidth, winHeight); + + event_loop(dpy, win, ctx1, ctx2); + + glDeleteLists(gear1, 1); + glDeleteLists(gear2, 1); + glXDestroyContext(dpy, ctx1); + glXDestroyContext(dpy, ctx2); + XDestroyWindow(dpy, win); + XCloseDisplay(dpy); + + return 0; +} diff --git a/progs/xdemos/opencloseopen.c b/progs/xdemos/opencloseopen.c index 0b8d061843..756096095e 100644 --- a/progs/xdemos/opencloseopen.c +++ b/progs/xdemos/opencloseopen.c @@ -158,7 +158,7 @@ main(int argc, char *argv[]) Display *dpy; Window win; GLXContext ctx; - char *dpyName = ":0"; + char *dpyName = NULL; int i; for (i = 1; i < argc; i++) { diff --git a/progs/xdemos/overlay.c b/progs/xdemos/overlay.c index 4c425b64d4..758f85c449 100644 --- a/progs/xdemos/overlay.c +++ b/progs/xdemos/overlay.c @@ -165,7 +165,8 @@ MakeOverlayWindow(Display *dpy) /* XXX setup the colormap entries! */ } else { - printf("Error: couldn't get an overlay visual!\n"); + printf("Couldn't get an overlay visual.\n"); + printf("Your hardware probably doesn't support framebuffer overlay planes.\n"); exit(1); } } diff --git a/progs/xdemos/sharedtex_mt.c b/progs/xdemos/sharedtex_mt.c new file mode 100644 index 0000000000..07c1bfcc38 --- /dev/null +++ b/progs/xdemos/sharedtex_mt.c @@ -0,0 +1,486 @@ +/* $Id: sharedtex.c,v 1.2 2002/01/16 14:32:46 joukj Exp $ */ + +/* + * Test sharing of display lists and texture objects between GLX contests. + * Brian Paul + * Summer 2000 + * + * + * Copyright (C) 2000 Brian Paul 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. + * + * + * Modified 2009 for multithreading by Thomas Hellstrom. + */ + + +#include <GL/gl.h> +#include <GL/glx.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <pthread.h> +#include <X11/X.h> + +struct thread_init_arg { + int id; +}; + +struct window { + pthread_mutex_t drawMutex; + char DisplayName[1000]; + Display *Dpy; + Window Win; + GLXContext Context; + float Angle; + int Id; + XVisualInfo *visInfo; +}; + + +#define MAX_WINDOWS 20 +static struct window Windows[MAX_WINDOWS]; +static int NumWindows = 0; +static int terminate = 0; +static GLXContext gCtx; +static Display *gDpy; +static GLuint Textures[3]; + + + +static void +Error(const char *display, const char *msg) +{ + fprintf(stderr, "Error on display %s - %s\n", display, msg); + exit(1); +} + + +static int +initMainthread(Display *dpy, const char *displayName) +{ + int scrnum; + XVisualInfo *visinfo; + int attrib[] = { GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + GLX_DOUBLEBUFFER, + GLX_DEPTH_SIZE, 1, + None }; + + scrnum = DefaultScreen(dpy); + visinfo = glXChooseVisual(dpy, scrnum, attrib); + if (!visinfo) { + Error(displayName, "Unable to find RGB, double-buffered visual"); + return -1; + } + gCtx = glXCreateContext(dpy, visinfo, NULL, True); + if (!gCtx) { + Error(displayName, "Couldn't create GLX context"); + return -1; + } + return 0; +} + +static struct window * +AddWindow(Display *dpy, const char *displayName, int xpos, int ypos, + GLXContext sCtx) +{ + Window win; + GLXContext ctx; + int attrib[] = { GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + GLX_DOUBLEBUFFER, + GLX_DEPTH_SIZE, 1, + None }; + int scrnum; + XSetWindowAttributes attr; + unsigned long mask; + Window root; + XVisualInfo *visinfo; + int width = 300, height = 300; + + if (NumWindows >= MAX_WINDOWS) + return NULL; + + scrnum = DefaultScreen(dpy); + root = RootWindow(dpy, scrnum); + + visinfo = glXChooseVisual(dpy, scrnum, attrib); + if (!visinfo) { + Error(displayName, "Unable to find RGB, double-buffered visual"); + return NULL; + } + + /* 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 = CWBorderPixel | CWColormap | CWEventMask; + + win = XCreateWindow(dpy, root, xpos, ypos, width, height, + 0, visinfo->depth, InputOutput, + visinfo->visual, mask, &attr); + if (!win) { + Error(displayName, "Couldn't create window"); + return NULL; + } + + { + XSizeHints sizehints; + sizehints.x = xpos; + sizehints.y = ypos; + sizehints.width = width; + sizehints.height = height; + sizehints.flags = USSize | USPosition; + XSetNormalHints(dpy, win, &sizehints); + XSetStandardProperties(dpy, win, displayName, displayName, + None, (char **)NULL, 0, &sizehints); + } + + + ctx = glXCreateContext(dpy, visinfo, + sCtx ? sCtx : NULL, True); + + if (!ctx) { + Error(displayName, "Couldn't create GLX context"); + return NULL; + } + + XMapWindow(dpy, win); + + /* save the info for this window */ + { + static int id = 0; + struct window *h = &Windows[NumWindows]; + strcpy(h->DisplayName, displayName); + h->Dpy = dpy; + h->Win = win; + h->Context = ctx; + h->Angle = 0.0; + h->Id = id++; + h->visInfo = visinfo; + pthread_mutex_init(&h->drawMutex, NULL); + NumWindows++; + return &Windows[NumWindows-1]; + } +} + + +static void +InitGLstuff(void) + +{ + glGenTextures(3, Textures); + + /* setup first texture object */ + { + GLubyte image[16][16][4]; + GLint i, j; + glBindTexture(GL_TEXTURE_2D, Textures[0]); + + /* red/white checkerboard */ + for (i = 0; i < 16; i++) { + for (j = 0; j < 16; j++) { + if ((i ^ j) & 1) { + image[i][j][0] = 255; + image[i][j][1] = 255; + image[i][j][2] = 255; + image[i][j][3] = 255; + } + else { + image[i][j][0] = 255; + image[i][j][1] = 0; + image[i][j][2] = 0; + image[i][j][3] = 255; + } + } + } + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, + GL_UNSIGNED_BYTE, image); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + + /* setup second texture object */ + { + GLubyte image[8][8][3]; + GLint i, j; + glBindTexture(GL_TEXTURE_2D, Textures[1]); + + /* green/yellow checkerboard */ + for (i = 0; i < 8; i++) { + for (j = 0; j < 8; j++) { + if ((i ^ j) & 1) { + image[i][j][0] = 0; + image[i][j][1] = 255; + image[i][j][2] = 0; + } + else { + image[i][j][0] = 255; + image[i][j][1] = 255; + image[i][j][2] = 0; + } + } + } + + glPixelStorei(GL_UNPACK_ALIGNMENT, 2); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, + GL_UNSIGNED_BYTE, image); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + + /* setup second texture object */ + { + GLubyte image[4][4][3]; + GLint i, j; + glBindTexture(GL_TEXTURE_2D, Textures[2]); + + /* blue/gray checkerboard */ + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + if ((i ^ j) & 1) { + image[i][j][0] = 0; + image[i][j][1] = 0; + image[i][j][2] = 255; + } + else { + image[i][j][0] = 200; + image[i][j][1] = 200; + image[i][j][2] = 200; + } + } + } + + glPixelStorei(GL_UNPACK_ALIGNMENT, 2); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 4, 4, 0, GL_RGB, + GL_UNSIGNED_BYTE, image); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + + /* Now make the cube object display list */ + + 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)); +} + +static void +Redraw(struct window *h) +{ + pthread_mutex_lock(&h->drawMutex); + if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) { + Error(h->DisplayName, "glXMakeCurrent failed in Redraw"); + pthread_mutex_unlock(&h->drawMutex); + return; + } + + h->Angle += 1.0; + + glShadeModel(GL_FLAT); + glClearColor(0.25, 0.25, 0.25, 1.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glEnable(GL_TEXTURE_2D); + glEnable(GL_DEPTH_TEST); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + + glColor3f(1, 1, 1); + + glPushMatrix(); + if (h->Id == 0) + glRotatef(h->Angle, 0, 1, -1); + else if (h->Id == 1) + glRotatef(-(h->Angle), 0, 1, -1); + else if (h->Id == 2) + glRotatef(h->Angle, 0, 1, 1); + else if (h->Id == 3) + glRotatef(-(h->Angle), 0, 1, 1); + glBindTexture(GL_TEXTURE_2D, Textures[0]); + glBegin(GL_POLYGON); + glTexCoord2f(0, 0); glVertex3f(-1, -1, -1); + glTexCoord2f(1, 0); glVertex3f(-1, 1, -1); + glTexCoord2f(1, 1); glVertex3f(-1, 1, 1); + glTexCoord2f(0, 1); glVertex3f(-1, -1, 1); + glEnd(); + glBegin(GL_POLYGON); + glTexCoord2f(0, 0); glVertex3f(1, -1, -1); + glTexCoord2f(1, 0); glVertex3f(1, 1, -1); + glTexCoord2f(1, 1); glVertex3f(1, 1, 1); + glTexCoord2f(0, 1); glVertex3f(1, -1, 1); + glEnd(); + + glBindTexture(GL_TEXTURE_2D, Textures[1]); + glBegin(GL_POLYGON); + glTexCoord2f(0, 0); glVertex3f(-1, -1, -1); + glTexCoord2f(1, 0); glVertex3f( 1, -1, -1); + glTexCoord2f(1, 1); glVertex3f( 1, -1, 1); + glTexCoord2f(0, 1); glVertex3f(-1, -1, 1); + glEnd(); + glBegin(GL_POLYGON); + glTexCoord2f(0, 0); glVertex3f(-1, 1, -1); + glTexCoord2f(1, 0); glVertex3f( 1, 1, -1); + glTexCoord2f(1, 1); glVertex3f( 1, 1, 1); + glTexCoord2f(0, 1); glVertex3f(-1, 1, 1); + glEnd(); + + glBindTexture(GL_TEXTURE_2D, Textures[2]); + glBegin(GL_POLYGON); + glTexCoord2f(0, 0); glVertex3f(-1, -1, -1); + glTexCoord2f(1, 0); glVertex3f( 1, -1, -1); + glTexCoord2f(1, 1); glVertex3f( 1, 1, -1); + glTexCoord2f(0, 1); glVertex3f(-1, 1, -1); + glEnd(); + glBegin(GL_POLYGON); + glTexCoord2f(0, 0); glVertex3f(-1, -1, 1); + glTexCoord2f(1, 0); glVertex3f( 1, -1, 1); + glTexCoord2f(1, 1); glVertex3f( 1, 1, 1); + glTexCoord2f(0, 1); glVertex3f(-1, 1, 1); + glEnd(); + + glPopMatrix(); + + glXSwapBuffers(h->Dpy, h->Win); + + if (!glXMakeCurrent(h->Dpy, None, NULL)) { + Error(h->DisplayName, "glXMakeCurrent failed in Redraw"); + } + pthread_mutex_unlock(&h->drawMutex); +} + +static void *threadRunner (void *arg) +{ + struct thread_init_arg *tia = (struct thread_init_arg *) arg; + struct window *win; + + win = &Windows[tia->id]; + + while(!terminate) { + usleep(1000); + Redraw(win); + } + + return NULL; +} + +static void +Resize(struct window *h, unsigned int width, unsigned int height) +{ + pthread_mutex_lock(&h->drawMutex); + + if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) { + Error(h->DisplayName, "glXMakeCurrent failed in Resize()"); + pthread_mutex_unlock(&h->drawMutex); + return; + } + + glViewport(0, 0, width, height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-1, 1, -1, 1, 2, 10); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0, 0, -4.5); + if (!glXMakeCurrent(h->Dpy, None, NULL)) { + Error(h->DisplayName, "glXMakeCurrent failed in Resize()"); + } + pthread_mutex_unlock(&h->drawMutex); +} + + +static void +EventLoop(void) +{ + while (1) { + int i; + XEvent event; + XNextEvent(gDpy, &event); + for (i = 0; i < NumWindows; i++) { + struct window *h = &Windows[i]; + if (event.xany.window == h->Win) { + switch (event.type) { + case Expose: + Redraw(h); + break; + case ConfigureNotify: + Resize(h, event.xconfigure.width, event.xconfigure.height); + break; + case KeyPress: + terminate = 1; + return; + default: + /*no-op*/ ; + } + } + } + } +} + +int +main(int argc, char *argv[]) +{ + const char *dpyName = XDisplayName(NULL); + pthread_t t0, t1, t2, t3; + struct thread_init_arg tia0, tia1, tia2, tia3; + struct window *h0, *h1, *h2, *h3; + + XInitThreads(); + + gDpy = XOpenDisplay(dpyName); + if (!gDpy) { + Error(dpyName, "Unable to open display"); + return -1; + } + + if (initMainthread(gDpy, dpyName)) + return -1; + + /* four windows and contexts sharing display lists and texture objects */ + h0 = AddWindow(gDpy, dpyName, 10, 10, gCtx); + h1 = AddWindow(gDpy, dpyName, 330, 10, gCtx); + h2 = AddWindow(gDpy, dpyName, 10, 350, gCtx); + h3 = AddWindow(gDpy, dpyName, 330, 350, gCtx); + + if (!glXMakeCurrent(gDpy, h0->Win, gCtx)) { + Error(dpyName, "glXMakeCurrent failed for init thread."); + return -1; + } + + InitGLstuff(); + + tia0.id = 0; + pthread_create(&t0, NULL, threadRunner, &tia0); + tia1.id = 1; + pthread_create(&t1, NULL, threadRunner, &tia1); + tia2.id = 2; + pthread_create(&t2, NULL, threadRunner, &tia2); + tia3.id = 3; + pthread_create(&t3, NULL, threadRunner, &tia3); + EventLoop(); + return 0; +} |