summaryrefslogtreecommitdiff
path: root/progs/xdemos
diff options
context:
space:
mode:
Diffstat (limited to 'progs/xdemos')
-rw-r--r--progs/xdemos/.gitignore2
-rw-r--r--progs/xdemos/Makefile32
-rw-r--r--progs/xdemos/descrip.mms83
-rw-r--r--progs/xdemos/glsync.c2
-rw-r--r--progs/xdemos/glthreads.c285
-rw-r--r--progs/xdemos/glxcontexts.c163
-rw-r--r--progs/xdemos/glxgears.c72
-rw-r--r--progs/xdemos/glxheads.c3
-rw-r--r--progs/xdemos/glxpixmap.c1
-rw-r--r--progs/xdemos/glxswapcontrol.c15
-rw-r--r--progs/xdemos/manywin.c2
-rw-r--r--progs/xdemos/multictx.c585
-rw-r--r--progs/xdemos/opencloseopen.c2
-rw-r--r--progs/xdemos/overlay.c3
-rw-r--r--progs/xdemos/sharedtex_mt.c486
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;
+}