aboutsummaryrefslogtreecommitdiffstats
path: root/progs/xdemos
diff options
context:
space:
mode:
Diffstat (limited to 'progs/xdemos')
-rw-r--r--progs/xdemos/.gitignore25
-rw-r--r--progs/xdemos/Makefile14
-rw-r--r--progs/xdemos/corender.c400
-rw-r--r--progs/xdemos/glthreads.c25
-rw-r--r--progs/xdemos/glxgears.c196
-rw-r--r--progs/xdemos/glxgears_pixmap.c (renamed from progs/xdemos/glxgears2.c)179
-rw-r--r--progs/xdemos/glxinfo.c285
-rw-r--r--progs/xdemos/glxsnoop.c377
-rw-r--r--progs/xdemos/glxswapcontrol.c5
-rw-r--r--progs/xdemos/ipc.c264
-rw-r--r--progs/xdemos/ipc.h16
-rw-r--r--progs/xdemos/offset.c32
-rw-r--r--progs/xdemos/pbutil.c72
-rw-r--r--progs/xdemos/pbutil.h3
-rw-r--r--progs/xdemos/sharedtex.c324
-rw-r--r--progs/xdemos/texture_from_pixmap.c396
16 files changed, 2375 insertions, 238 deletions
diff --git a/progs/xdemos/.gitignore b/progs/xdemos/.gitignore
new file mode 100644
index 00000000000..868249db884
--- /dev/null
+++ b/progs/xdemos/.gitignore
@@ -0,0 +1,25 @@
+corender
+glthreads
+glxcontexts
+glxdemo
+glxgears
+glxgears_fbconfig
+glxgears_pixmap
+glxheads
+glxinfo
+glxpbdemo
+glxpixmap
+glxsnoop
+glxswapcontrol
+manywin
+offset
+overlay
+pbdemo
+pbinfo
+sharedtex
+texture_from_pixmap
+wincopy
+xdemo
+xfont
+xrotfontdemo
+yuvrect_client
diff --git a/progs/xdemos/Makefile b/progs/xdemos/Makefile
index 1803633ef11..c90159bd38c 100644
--- a/progs/xdemos/Makefile
+++ b/progs/xdemos/Makefile
@@ -11,21 +11,26 @@ LIB_DEP = $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME)
LIBS = -L$(TOP)/$(LIB_DIR) -l$(GL_LIB) $(APP_LIB_DEPS)
PROGS = \
+ corender \
glthreads \
glxdemo \
glxgears \
glxgears_fbconfig \
+ glxgears_pixmap \
glxcontexts \
glxheads \
glxinfo \
glxpixmap \
glxpbdemo \
+ glxsnoop \
glxswapcontrol \
manywin \
offset \
overlay \
pbinfo \
pbdemo \
+ sharedtex \
+ texture_from_pixmap \
wincopy \
xfont \
xrotfontdemo
@@ -91,6 +96,15 @@ xuserotfont.o: xuserotfont.c xuserotfont.h
xrotfontdemo.o: xrotfontdemo.c xuserotfont.h
$(CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) xrotfontdemo.c
+corender: corender.o ipc.o
+ $(CC) $(CFLAGS) corender.o ipc.o $(LIBS) -o $@
+
+corender.o: corender.c ipc.h
+ $(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
+
yuvrect_client: yuvrect_client.c
$(CC) -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) $< $(LDFLAGS) $(LIBS) -l$(GLU_LIB) -o $@
diff --git a/progs/xdemos/corender.c b/progs/xdemos/corender.c
new file mode 100644
index 00000000000..f2b8145e52b
--- /dev/null
+++ b/progs/xdemos/corender.c
@@ -0,0 +1,400 @@
+/**
+ * Example of cooperative rendering into one window by two processes.
+ * The first instance of the program creates the GLX window.
+ * The second instance of the program gets the window ID from the first
+ * and draws into it.
+ * Socket IPC is used for synchronization.
+ *
+ * Usage:
+ * 1. run 'corender &'
+ * 2. run 'corender 2' (any arg will do)
+ *
+ * Brian Paul
+ * 11 Oct 2007
+ */
+
+
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <X11/keysym.h>
+#include <unistd.h>
+#include "ipc.h"
+
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+static int MyID = 0; /* 0 or 1 */
+static int WindowID = 0;
+static GLXContext Context = 0;
+static int Width = 700, Height = 350;
+static int Rot = 0;
+static int Sock = 0;
+
+static GLfloat Red[4] = {1.0, 0.2, 0.2, 1.0};
+static GLfloat Blue[4] = {0.2, 0.2, 1.0, 1.0};
+
+static int Sync = 1; /** synchronized rendering? */
+
+
+static void
+setup_ipc(void)
+{
+ int k, port = 10001;
+
+ if (MyID == 0) {
+ /* I'm the first one, wait for connection from second */
+ k = CreatePort(&port);
+ assert(k != -1);
+
+ printf("Waiting for connection from another 'corender'\n");
+ Sock = AcceptConnection(k);
+
+ printf("Got connection, sending windowID\n");
+
+ /* send windowID */
+ SendData(Sock, &WindowID, sizeof(WindowID));
+ }
+ else {
+ /* I'm the second one, connect to first */
+ char hostname[1000];
+
+ MyHostName(hostname, 1000);
+ Sock = Connect(hostname, port);
+ assert(Sock != -1);
+
+ /* get windowID */
+ ReceiveData(Sock, &WindowID, sizeof(WindowID));
+ printf("Contacted first 'corender', getting WindowID\n");
+ }
+}
+
+
+
+/** from GLUT */
+static void
+doughnut(GLfloat r, GLfloat R, GLint nsides, GLint rings)
+{
+ int i, j;
+ GLfloat theta, phi, theta1;
+ GLfloat cosTheta, sinTheta;
+ GLfloat cosTheta1, sinTheta1;
+ GLfloat ringDelta, sideDelta;
+
+ ringDelta = 2.0 * M_PI / rings;
+ sideDelta = 2.0 * M_PI / nsides;
+
+ theta = 0.0;
+ cosTheta = 1.0;
+ sinTheta = 0.0;
+ for (i = rings - 1; i >= 0; i--) {
+ theta1 = theta + ringDelta;
+ cosTheta1 = cos(theta1);
+ sinTheta1 = sin(theta1);
+ glBegin(GL_QUAD_STRIP);
+ phi = 0.0;
+ for (j = nsides; j >= 0; j--) {
+ GLfloat cosPhi, sinPhi, dist;
+
+ phi += sideDelta;
+ cosPhi = cos(phi);
+ sinPhi = sin(phi);
+ dist = R + r * cosPhi;
+
+ glNormal3f(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi);
+ glVertex3f(cosTheta1 * dist, -sinTheta1 * dist, r * sinPhi);
+ glNormal3f(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi);
+ glVertex3f(cosTheta * dist, -sinTheta * dist, r * sinPhi);
+ }
+ glEnd();
+ theta = theta1;
+ cosTheta = cosTheta1;
+ sinTheta = sinTheta1;
+ }
+}
+
+
+static void
+redraw(Display *dpy)
+{
+ int dbg = 0;
+
+ glXMakeCurrent(dpy, WindowID, Context);
+ glEnable(GL_LIGHTING);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_DEPTH_TEST);
+ glClearColor(0.5, 0.5, 0.5, 0.0);
+
+ if (MyID == 0) {
+ /* First process */
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glPushMatrix();
+ glTranslatef(-1, 0, 0);
+ glRotatef(Rot, 1, 0, 0);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Red);
+ doughnut(0.5, 2.0, 20, 30);
+ glPopMatrix();
+
+ glFinish();
+ if (!Sync) {
+ usleep(1000*10);
+ }
+
+ /* signal second process to render */
+ if (Sync) {
+ int code = 1;
+ if (dbg) printf("0: send signal\n");
+ SendData(Sock, &code, sizeof(code));
+ SendData(Sock, &Rot, sizeof(Rot));
+ }
+
+ /* wait for second process to finish rendering */
+ if (Sync) {
+ int code = 0;
+ if (dbg) printf("0: wait signal\n");
+ ReceiveData(Sock, &code, sizeof(code));
+ if (dbg) printf("0: got signal\n");
+ assert(code == 2);
+ }
+
+ }
+ else {
+ /* Second process */
+
+ /* wait for first process's signal for me to render */
+ if (Sync) {
+ int code = 0;
+ if (dbg) printf("1: wait signal\n");
+ ReceiveData(Sock, &code, sizeof(code));
+ ReceiveData(Sock, &Rot, sizeof(Rot));
+
+ if (dbg) printf("1: got signal\n");
+ assert(code == 1);
+ }
+
+ /* XXX this clear should not be here, but for some reason, it
+ * makes things _mostly_ work correctly w/ NVIDIA's driver.
+ * There's only occasional glitches.
+ * Without this glClear(), depth buffer for the second process
+ * is pretty much broken.
+ */
+ //glClear(GL_DEPTH_BUFFER_BIT);
+
+ glPushMatrix();
+ glTranslatef(1, 0, 0);
+ glRotatef(Rot + 90 , 1, 0, 0);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Blue);
+ doughnut(0.5, 2.0, 20, 30);
+ glPopMatrix();
+ glFinish();
+
+ glXSwapBuffers(dpy, WindowID);
+ usleep(1000*10);
+
+ /* signal first process that I'm done rendering */
+ if (Sync) {
+ int code = 2;
+ if (dbg) printf("1: send signal\n");
+ SendData(Sock, &code, sizeof(code));
+ }
+ }
+}
+
+
+static void
+resize(Display *dpy, int width, int height)
+{
+ float ar = (float) width / height;
+
+ glXMakeCurrent(dpy, WindowID, Context);
+
+ glViewport(0, 0, width, height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(-ar, ar, 1.0, -1.0, 5.0, 200.0);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glTranslatef(0, 0, -15);
+
+ Width = width;
+ Height = height;
+}
+
+
+
+static void
+set_window_title(Display *dpy, Window win, const char *title)
+{
+ XSizeHints sizehints;
+ sizehints.flags = 0;
+ XSetStandardProperties(dpy, win, title, title,
+ None, (char **)NULL, 0, &sizehints);
+}
+
+
+static Window
+make_gl_window(Display *dpy, XVisualInfo *visinfo, int width, int height)
+{
+ int scrnum;
+ XSetWindowAttributes attr;
+ unsigned long mask;
+ Window root;
+ Window win;
+ int x = 0, y = 0;
+ char *name = NULL;
+
+ scrnum = DefaultScreen( dpy );
+ root = RootWindow( dpy, scrnum );
+
+ /* window attributes */
+ attr.background_pixel = 0;
+ attr.border_pixel = 0;
+ attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
+ attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
+ mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+ win = XCreateWindow( dpy, root, x, y, width, height,
+ 0, visinfo->depth, InputOutput,
+ visinfo->visual, mask, &attr );
+
+ /* set hints and properties */
+ {
+ XSizeHints sizehints;
+ sizehints.x = x;
+ sizehints.y = y;
+ sizehints.width = width;
+ sizehints.height = height;
+ sizehints.flags = USSize | USPosition;
+ XSetNormalHints(dpy, win, &sizehints);
+ XSetStandardProperties(dpy, win, name, name,
+ None, (char **)NULL, 0, &sizehints);
+ }
+
+ return win;
+}
+
+
+static void
+set_event_mask(Display *dpy, Window win)
+{
+ XSetWindowAttributes attr;
+ attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
+ XChangeWindowAttributes(dpy, win, CWEventMask, &attr);
+}
+
+
+static void
+event_loop(Display *dpy)
+{
+ while (1) {
+ while (XPending(dpy) > 0) {
+ XEvent event;
+ XNextEvent(dpy, &event);
+
+ switch (event.type) {
+ case Expose:
+ redraw(dpy);
+ break;
+ case ConfigureNotify:
+ resize(dpy, event.xconfigure.width, event.xconfigure.height);
+ break;
+ case KeyPress:
+ {
+ char buffer[10];
+ int r, code;
+ code = XLookupKeysym(&event.xkey, 0);
+ if (code == XK_Left) {
+ }
+ else {
+ r = XLookupString(&event.xkey, buffer, sizeof(buffer),
+ NULL, NULL);
+ if (buffer[0] == 27) {
+ exit(0);
+ }
+ }
+ }
+ default:
+ /* nothing */
+ ;
+ }
+ }
+
+ if (MyID == 0 || !Sync)
+ Rot += 1;
+ redraw(dpy);
+ }
+}
+
+
+static XVisualInfo *
+choose_visual(Display *dpy)
+{
+ int attribs[] = { GLX_RGBA,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_DOUBLEBUFFER,
+ GLX_DEPTH_SIZE, 1,
+ None };
+ int scrnum = DefaultScreen( dpy );
+ return glXChooseVisual(dpy, scrnum, attribs);
+}
+
+
+static void
+parse_opts(int argc, char *argv[])
+{
+ if (argc > 1) {
+ MyID = 1;
+ }
+}
+
+
+int
+main( int argc, char *argv[] )
+{
+ Display *dpy;
+ XVisualInfo *visinfo;
+
+ parse_opts(argc, argv);
+
+ dpy = XOpenDisplay(NULL);
+
+ visinfo = choose_visual(dpy);
+
+ Context = glXCreateContext( dpy, visinfo, NULL, True );
+ if (!Context) {
+ printf("Error: glXCreateContext failed\n");
+ exit(1);
+ }
+
+ if (MyID == 0) {
+ WindowID = make_gl_window(dpy, visinfo, Width, Height);
+ set_window_title(dpy, WindowID, "corender");
+ XMapWindow(dpy, WindowID);
+ /*printf("WindowID 0x%x\n", (int) WindowID);*/
+ }
+
+ /* do ipc hand-shake here */
+ setup_ipc();
+ assert(Sock);
+ assert(WindowID);
+
+ if (MyID == 1) {
+ set_event_mask(dpy, WindowID);
+ }
+
+ resize(dpy, Width, Height);
+
+ event_loop(dpy);
+
+ return 0;
+}
diff --git a/progs/xdemos/glthreads.c b/progs/xdemos/glthreads.c
index 6c7029b6ecf..4f87ee75d40 100644
--- a/progs/xdemos/glthreads.c
+++ b/progs/xdemos/glthreads.c
@@ -24,6 +24,7 @@
* This program tests GLX thread safety.
* Command line options:
* -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)
*
@@ -405,6 +406,19 @@ clean_up(void)
}
+static void
+usage(void)
+{
+ printf("glthreads: test of GL thread safety (any key = exit)\n");
+ printf("Usage:\n");
+ printf(" glthreads [options]\n");
+ printf("Options:\n");
+ printf(" -display DISPLAYNAME Specify display string\n");
+ 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");
+}
+
int
main(int argc, char *argv[])
@@ -416,9 +430,7 @@ main(int argc, char *argv[])
Status threadStat;
if (argc == 1) {
- printf("glthreads: test of GL thread safety (any key = exit)\n");
- printf("Usage:\n");
- printf(" glthreads [-display dpyName] [-n numthreads]\n");
+ usage();
}
else {
int i;
@@ -442,13 +454,14 @@ main(int argc, char *argv[])
i++;
}
else {
- fprintf(stderr, "glthreads: unexpected flag: %s\n", argv[i]);
+ usage();
+ exit(1);
}
}
}
if (Locking)
- printf("glthreads: Using explict locks around Xlib calls.\n");
+ printf("glthreads: Using explicit locks around Xlib calls.\n");
else
printf("glthreads: No explict locking.\n");
@@ -505,7 +518,7 @@ main(int argc, char *argv[])
for (i = 0; i < numThreads; i++) {
pthread_create(&WinThreads[i].Thread, NULL, thread_function,
(void*) &WinThreads[i]);
- printf("glthreads: Created thread %p\n", WinThreads[i].Thread);
+ printf("glthreads: Created thread %p\n", (void *) WinThreads[i].Thread);
}
if (MultiDisplays)
diff --git a/progs/xdemos/glxgears.c b/progs/xdemos/glxgears.c
index 75d63e51a2e..c98c3157b5d 100644
--- a/progs/xdemos/glxgears.c
+++ b/progs/xdemos/glxgears.c
@@ -88,12 +88,18 @@ current_time(void)
#endif
+/** Event handler results: */
+#define NOP 0
+#define EXIT 1
+#define DRAW 2
+
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 GLboolean animate = GL_TRUE; /* Animation */
static GLfloat eyesep = 5.0; /* Eye separation. */
static GLfloat fix_point = 40.0; /* Fixation point distance. */
static GLfloat left, right, asp; /* Stereo frustum params. */
@@ -239,7 +245,7 @@ gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
static void
-do_draw(void)
+draw(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -269,8 +275,9 @@ do_draw(void)
glPopMatrix();
}
+
static void
-draw(void)
+draw_gears(void)
{
if (stereo) {
/* First left eye. */
@@ -284,7 +291,7 @@ draw(void)
glPushMatrix();
glTranslated(+0.5 * eyesep, 0.0, 0.0);
- do_draw();
+ draw();
glPopMatrix();
/* Then right eye. */
@@ -298,10 +305,50 @@ draw(void)
glPushMatrix();
glTranslated(-0.5 * eyesep, 0.0, 0.0);
- do_draw();
+ draw();
glPopMatrix();
- } else
- do_draw();
+ }
+ else {
+ draw();
+ }
+}
+
+
+/** Draw single frame, do SwapBuffers, compute FPS */
+static void
+draw_frame(Display *dpy, Window win)
+{
+ static int frames = 0;
+ static double tRot0 = -1.0, tRate0 = -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;
+ }
+
+ draw_gears();
+ glXSwapBuffers(dpy, win);
+
+ frames++;
+
+ if (tRate0 < 0.0)
+ tRate0 = t;
+ if (t - tRate0 >= 5.0) {
+ GLfloat seconds = t - tRate0;
+ GLfloat fps = frames / seconds;
+ printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds,
+ fps);
+ tRate0 = t;
+ frames = 0;
+ }
}
@@ -319,7 +366,8 @@ reshape(int width, int height)
left = -5.0 * ((w - 0.5 * eyesep) / fix_point);
right = 5.0 * ((w + 0.5 * eyesep) / fix_point);
- } else {
+ }
+ else {
GLfloat h = (GLfloat) height / (GLfloat) width;
glMatrixMode(GL_PROJECTION);
@@ -430,10 +478,11 @@ 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;
+ /* XXX this is a bad way to get a borderless window! */
attr.override_redirect = fullscreen;
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect;
- win = XCreateWindow( dpy, root, 0, 0, width, height,
+ win = XCreateWindow( dpy, root, x, y, width, height,
0, visinfo->depth, InputOutput,
visinfo->visual, mask, &attr );
@@ -463,79 +512,70 @@ make_window( Display *dpy, const char *name,
}
+/**
+ * Handle one X event.
+ * \return NOP, EXIT or DRAW
+ */
+static int
+handle_event(Display *dpy, Window win, XEvent *event)
+{
+ switch (event->type) {
+ case Expose:
+ return DRAW;
+ case ConfigureNotify:
+ reshape(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)
{
while (1) {
- while (XPending(dpy) > 0) {
+ int op;
+ while (!animate || XPending(dpy) > 0) {
XEvent event;
XNextEvent(dpy, &event);
- switch (event.type) {
- case Expose:
- /* we'll redraw below */
- break;
- case ConfigureNotify:
- reshape(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;
- }
- }
- }
- }
+ op = handle_event(dpy, win, &event);
+ if (op == EXIT)
+ return;
+ else if (op == DRAW)
+ break;
}
- {
- static int frames = 0;
- static double tRot0 = -1.0, tRate0 = -1.0;
- double dt, t = current_time();
- if (tRot0 < 0.0)
- tRot0 = t;
- dt = t - tRot0;
- tRot0 = t;
-
- /* advance rotation for next frame */
- angle += 70.0 * dt; /* 70 degrees per second */
- if (angle > 3600.0)
- angle -= 3600.0;
-
- draw();
- glXSwapBuffers(dpy, win);
-
- frames++;
-
- if (tRate0 < 0.0)
- tRate0 = t;
- if (t - tRate0 >= 5.0) {
- GLfloat seconds = t - tRate0;
- GLfloat fps = frames / seconds;
- printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds,
- fps);
- tRate0 = t;
- frames = 0;
- }
- }
+ draw_frame(dpy, win);
}
}
@@ -548,13 +588,15 @@ usage(void)
printf(" -stereo run in stereo mode\n");
printf(" -fullscreen run in fullscreen mode\n");
printf(" -info display OpenGL renderer info\n");
+ printf(" -geometry WxH+X+Y window geometry\n");
}
int
main(int argc, char *argv[])
{
- const int winWidth = 300, winHeight = 300;
+ unsigned int winWidth = 300, winHeight = 300;
+ int x = 0, y = 0;
Display *dpy;
Window win;
GLXContext ctx;
@@ -576,6 +618,10 @@ main(int argc, char *argv[])
else if (strcmp(argv[i], "-fullscreen") == 0) {
fullscreen = GL_TRUE;
}
+ else if (i < argc-1 && strcmp(argv[i], "-geometry") == 0) {
+ XParseGeometry(argv[i+1], &x, &y, &winWidth, &winHeight);
+ i++;
+ }
else {
usage();
return -1;
@@ -589,7 +635,7 @@ main(int argc, char *argv[])
return -1;
}
- make_window(dpy, "glxgears", 0, 0, winWidth, winHeight, &win, &ctx);
+ make_window(dpy, "glxgears", x, y, winWidth, winHeight, &win, &ctx);
XMapWindow(dpy, win);
glXMakeCurrent(dpy, win, ctx);
diff --git a/progs/xdemos/glxgears2.c b/progs/xdemos/glxgears_pixmap.c
index 5de5601240e..661d130e41c 100644
--- a/progs/xdemos/glxgears2.c
+++ b/progs/xdemos/glxgears_pixmap.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
- *
+ * Copyright (C) 2008 Red Hat, Inc All Rights Reserved.
+ *
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
@@ -19,16 +20,22 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-/*
- * This is a port of the infamous "gears" demo to straight GLX (i.e. no GLUT)
- * Port by Brian Paul 23 March 2001
+/**
+ * \file glxgears_pixmap.c
+ * Yet-another-version of gears. Originally ported to GLX by Brian Paul on
+ * 23 March 2001. Modified to use fbconfigs by Ian Romanick on 10 Feb 2004.
*
* Command line options:
* -info print GL implementation information
*
+ * \author Brian Paul
+ * \author Ian Romanick <[email protected]>
+ * \author Kristian Hoegsberg <[email protected]>
*/
+#define GLX_GLXEXT_PROTOTYPES
+
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
@@ -37,7 +44,9 @@
#include <X11/keysym.h>
#include <GL/gl.h>
#include <GL/glx.h>
-
+#include <GL/glxext.h>
+#include <assert.h>
+#include "pbutil.h"
#define BENCHMARK
@@ -83,7 +92,7 @@ current_time(void)
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 GLint WinWidth = 300, WinHeight = 300;
+
/*
*
@@ -256,33 +265,33 @@ draw(void)
}
+struct gears {
+ Window win;
+ GLXContext ctx;
+ Pixmap pixmap;
+ GLXPixmap glxpixmap;
+ GC gc;
+ int width, height;
+};
+
+
/* new window size or exposure */
static void
-reshape(int width, int height)
+reshape(struct gears *gears, int width, int height)
{
- GLfloat h = (GLfloat) height / (GLfloat) width;
-
- glViewport(0, 0, (GLint) width, (GLint) height);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glTranslatef(0.0, 0.0, -40.0);
- WinWidth = width;
- WinHeight = height;
+ gears->width = width;
+ gears->height = height;
}
static void
-init(void)
+init(int width, int height)
{
static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 };
static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 };
static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };
-
- glClearColor(1, 0, 0, 0);
+ GLfloat h = (GLfloat) height / (GLfloat) width;
glLightfv(GL_LIGHT0, GL_POSITION, pos);
glEnable(GL_CULL_FACE);
@@ -310,8 +319,15 @@ init(void)
glEndList();
glEnable(GL_NORMALIZE);
-}
+ glViewport(0, 0, (GLint) width, (GLint) height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glTranslatef(0.0, 0.0, -40.0);
+}
/*
* Create an RGB, double-buffered window.
@@ -319,43 +335,48 @@ init(void)
*/
static void
make_window( Display *dpy, const char *name,
- int x, int y, int width, int height,
- Window *winRet, GLXContext *ctxRet)
+ int x, int y, int width, int height, struct gears *gears)
{
- int attrib[] = { GLX_RGBA,
- GLX_RED_SIZE, 1,
- GLX_GREEN_SIZE, 1,
- GLX_BLUE_SIZE, 1,
- GLX_DOUBLEBUFFER,
- GLX_DEPTH_SIZE, 1,
+ int attrib[] = { GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
+ GLX_RENDER_TYPE, GLX_RGBA_BIT,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_DOUBLEBUFFER, GL_FALSE,
+ GLX_DEPTH_SIZE, 1,
None };
+ GLXFBConfig * fbconfig;
+ int num_configs;
int scrnum;
XSetWindowAttributes attr;
unsigned long mask;
Window root;
- Window win;
- GLXContext ctx;
XVisualInfo *visinfo;
+ gears->width = width;
+ gears->height = height;
+
scrnum = DefaultScreen( dpy );
root = RootWindow( dpy, scrnum );
- visinfo = glXChooseVisual( dpy, scrnum, attrib );
- if (!visinfo) {
+ fbconfig = glXChooseFBConfig(dpy, scrnum, attrib, & num_configs);
+ if (fbconfig == NULL) {
printf("Error: couldn't get an RGB, Double-buffered visual\n");
exit(1);
}
/* window attributes */
+ visinfo = glXGetVisualFromFBConfig(dpy, fbconfig[0]);
+ assert(visinfo != NULL);
attr.background_pixel = 0;
attr.border_pixel = 0;
attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
- win = XCreateWindow( dpy, root, 0, 0, width, height,
- 0, visinfo->depth, InputOutput,
- visinfo->visual, mask, &attr );
+ gears->win = XCreateWindow( dpy, root, 0, 0, width, height,
+ 0, visinfo->depth, InputOutput,
+ visinfo->visual, mask, &attr );
/* set hints and properties */
{
@@ -365,27 +386,42 @@ make_window( Display *dpy, const char *name,
sizehints.width = width;
sizehints.height = height;
sizehints.flags = USSize | USPosition;
- XSetNormalHints(dpy, win, &sizehints);
- XSetStandardProperties(dpy, win, name, name,
+ XSetNormalHints(dpy, gears->win, &sizehints);
+ XSetStandardProperties(dpy, gears->win, name, name,
None, (char **)NULL, 0, &sizehints);
}
- ctx = glXCreateContext( dpy, visinfo, NULL, True );
- if (!ctx) {
- printf("Error: glXCreateContext failed\n");
- exit(1);
+ gears->gc = XCreateGC(dpy, gears->win, 0, NULL);
+
+ gears->pixmap = XCreatePixmap(dpy, gears->win,
+ width, height, visinfo->depth);
+ if (!gears->pixmap) {
+ printf("Error: XCreatePixmap failed\n");
+ exit(-1);
+ }
+
+ gears->glxpixmap = glXCreatePixmap(dpy, fbconfig[0], gears->pixmap, NULL);
+ if (!gears->glxpixmap) {
+ printf("Error: glXCreatePixmap failed\n");
+ exit(-1);
}
- XFree(visinfo);
+ gears->ctx = glXCreateNewContext(dpy, fbconfig[0],
+ GLX_RGBA_TYPE, NULL, GL_TRUE);
+ if (!gears->ctx) {
+ printf("Error: glXCreateNewContext failed\n");
+ exit(1);
+ }
- *winRet = win;
- *ctxRet = ctx;
+ XFree(fbconfig);
}
static void
-event_loop(Display *dpy, Window win)
+event_loop(Display *dpy, struct gears *gears)
{
+ int x, y;
+
while (1) {
while (XPending(dpy) > 0) {
XEvent event;
@@ -395,7 +431,7 @@ event_loop(Display *dpy, Window win)
/* we'll redraw below */
break;
case ConfigureNotify:
- reshape(event.xconfigure.width, event.xconfigure.height);
+ reshape(gears, event.xconfigure.width, event.xconfigure.height);
break;
case KeyPress:
{
@@ -430,24 +466,12 @@ event_loop(Display *dpy, Window win)
angle += 2.0;
draw();
+ glFinish();
-#if 0
- glXSwapBuffers(dpy, win);
-#else
- {
- GLfloat c[4];
-
- glReadBuffer(GL_BACK);
-
- glReadPixels(WinWidth-1, 0, 1, 1, GL_RGB, GL_FLOAT, c);
- printf("Bottom right pixel color: %g, %g, %g\n", c[0], c[1], c[2]);
-
- glDrawBuffer(GL_FRONT);
- glWindowPos2iARB(0,0);
- glCopyPixels(WinWidth/2, 0, WinWidth/2, WinHeight, GL_COLOR);
- glDrawBuffer(GL_BACK);
- }
-#endif
+ for (x = 0; x < gears->width; x += 100)
+ for (y = 0; y < gears->width; y += 100)
+ XCopyArea(dpy, gears->pixmap, gears->win, gears->gc,
+ 50, 50, 100, 100, x, y);
/* calc framerate */
{
@@ -477,11 +501,10 @@ int
main(int argc, char *argv[])
{
Display *dpy;
- Window win;
- GLXContext ctx;
- char *dpyName = ":0";
+ const char *dpyName = NULL;
GLboolean printInfo = GL_FALSE;
- int i;
+ struct gears gears;
+ int i, width = 200, height = 200;
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "-display") == 0) {
@@ -495,13 +518,13 @@ main(int argc, char *argv[])
dpy = XOpenDisplay(dpyName);
if (!dpy) {
- printf("Error: couldn't open display %s\n", dpyName);
+ printf("Error: couldn't open display %s\n", XDisplayName(dpyName));
return -1;
}
- make_window(dpy, "glxgears", 0, 0, WinWidth, WinHeight, &win, &ctx);
- XMapWindow(dpy, win);
- glXMakeCurrent(dpy, win, ctx);
+ make_window(dpy, "glxgears", 0, 0, width, height, &gears);
+ XMapWindow(dpy, gears.win);
+ glXMakeCurrent(dpy, gears.glxpixmap, gears.ctx);
if (printInfo) {
printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
@@ -510,12 +533,14 @@ main(int argc, char *argv[])
printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
}
- init();
+ init(width, height);
- event_loop(dpy, win);
+ event_loop(dpy, &gears);
- glXDestroyContext(dpy, ctx);
- XDestroyWindow(dpy, win);
+ glXDestroyContext(dpy, gears.ctx);
+ XDestroyWindow(dpy, gears.win);
+ glXDestroyPixmap(dpy, gears.pixmap);
+ XFreePixmap(dpy, gears.pixmap);
XCloseDisplay(dpy);
return 0;
diff --git a/progs/xdemos/glxinfo.c b/progs/xdemos/glxinfo.c
index e33cddff047..35b6ed16b09 100644
--- a/progs/xdemos/glxinfo.c
+++ b/progs/xdemos/glxinfo.c
@@ -52,6 +52,13 @@
#define GLX_TRANSPARENT_RGB 0x8008
#endif
+#ifndef GLX_RGBA_BIT
+#define GLX_RGBA_BIT 0x00000001
+#endif
+
+#ifndef GLX_COLOR_INDEX_BIT
+#define GLX_COLOR_INDEX_BIT 0x00000002
+#endif
typedef enum
{
@@ -81,7 +88,7 @@ struct visual_attribs
int transparentIndexValue;
int bufferSize;
int level;
- int rgba;
+ int render_type;
int doubleBuffer;
int stereo;
int auxBuffers;
@@ -388,20 +395,61 @@ print_screen_info(Display *dpy, int scrnum, Bool allowDirect, GLboolean limits)
XSetWindowAttributes attr;
unsigned long mask;
Window root;
- GLXContext ctx;
+ GLXContext ctx = NULL;
XVisualInfo *visinfo;
int width = 100, height = 100;
root = RootWindow(dpy, scrnum);
visinfo = glXChooseVisual(dpy, scrnum, attribSingle);
- if (!visinfo) {
+ if (!visinfo)
visinfo = glXChooseVisual(dpy, scrnum, attribDouble);
- if (!visinfo) {
- fprintf(stderr, "Error: couldn't find RGB GLX visual\n");
- return;
+
+ if (visinfo)
+ ctx = glXCreateContext( dpy, visinfo, NULL, allowDirect );
+
+#ifdef GLX_VERSION_1_3
+ {
+ int fbAttribSingle[] = {
+ GLX_RENDER_TYPE, GLX_RGBA_BIT,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_DOUBLEBUFFER, GL_TRUE,
+ None };
+ int fbAttribDouble[] = {
+ GLX_RENDER_TYPE, GLX_RGBA_BIT,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ None };
+ GLXFBConfig *configs = NULL;
+ int nConfigs;
+
+ if (!visinfo)
+ configs = glXChooseFBConfig(dpy, scrnum, fbAttribSingle, &nConfigs);
+ if (!visinfo)
+ configs = glXChooseFBConfig(dpy, scrnum, fbAttribDouble, &nConfigs);
+
+ if (configs) {
+ visinfo = glXGetVisualFromFBConfig(dpy, configs[0]);
+ ctx = glXCreateNewContext(dpy, configs[0], GLX_RGBA_TYPE, NULL, allowDirect);
+ XFree(configs);
}
}
+#endif
+
+ if (!visinfo) {
+ fprintf(stderr, "Error: couldn't find RGB GLX visual or fbconfig\n");
+ return;
+ }
+
+ if (!ctx) {
+ fprintf(stderr, "Error: glXCreateContext failed\n");
+ XFree(visinfo);
+ XDestroyWindow(dpy, win);
+ return;
+ }
attr.background_pixel = 0;
attr.border_pixel = 0;
@@ -412,14 +460,6 @@ print_screen_info(Display *dpy, int scrnum, Bool allowDirect, GLboolean limits)
0, visinfo->depth, InputOutput,
visinfo->visual, mask, &attr);
- ctx = glXCreateContext( dpy, visinfo, NULL, allowDirect );
- if (!ctx) {
- fprintf(stderr, "Error: glXCreateContext failed\n");
- XFree(visinfo);
- XDestroyWindow(dpy, win);
- return;
- }
-
if (glXMakeCurrent(dpy, win, ctx)) {
const char *serverVendor = glXQueryServerString(dpy, scrnum, GLX_VENDOR);
const char *serverVersion = glXQueryServerString(dpy, scrnum, GLX_VERSION);
@@ -541,12 +581,27 @@ visual_class_abbrev(int cls)
}
}
+static const char *
+visual_render_type_name(int type)
+{
+ switch (type) {
+ case GLX_RGBA_BIT:
+ return "rgba";
+ case GLX_COLOR_INDEX_BIT:
+ return "ci";
+ case GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT:
+ return "rgba|ci";
+ default:
+ return "";
+ }
+}
-static void
+static GLboolean
get_visual_attribs(Display *dpy, XVisualInfo *vInfo,
struct visual_attribs *attribs)
{
const char *ext = glXQueryExtensionsString(dpy, vInfo->screen);
+ int rgba;
memset(attribs, 0, sizeof(struct visual_attribs));
@@ -563,11 +618,17 @@ get_visual_attribs(Display *dpy, XVisualInfo *vInfo,
attribs->colormapSize = vInfo->colormap_size;
attribs->bitsPerRGB = vInfo->bits_per_rgb;
- if (glXGetConfig(dpy, vInfo, GLX_USE_GL, &attribs->supportsGL) != 0)
- return;
+ if (glXGetConfig(dpy, vInfo, GLX_USE_GL, &attribs->supportsGL) != 0 ||
+ !attribs->supportsGL)
+ return GL_FALSE;
glXGetConfig(dpy, vInfo, GLX_BUFFER_SIZE, &attribs->bufferSize);
glXGetConfig(dpy, vInfo, GLX_LEVEL, &attribs->level);
- glXGetConfig(dpy, vInfo, GLX_RGBA, &attribs->rgba);
+ glXGetConfig(dpy, vInfo, GLX_RGBA, &rgba);
+ if (rgba)
+ attribs->render_type = GLX_RGBA_BIT;
+ else
+ attribs->render_type = GLX_COLOR_INDEX_BIT;
+
glXGetConfig(dpy, vInfo, GLX_DOUBLEBUFFER, &attribs->doubleBuffer);
glXGetConfig(dpy, vInfo, GLX_STEREO, &attribs->stereo);
glXGetConfig(dpy, vInfo, GLX_AUX_BUFFERS, &attribs->auxBuffers);
@@ -616,8 +677,97 @@ get_visual_attribs(Display *dpy, XVisualInfo *vInfo,
#else
attribs->visualCaveat = 0;
#endif
+
+ return GL_TRUE;
}
+#ifdef GLX_VERSION_1_3
+
+static int
+glx_token_to_visual_class(int visual_type)
+{
+ switch (visual_type) {
+ case GLX_TRUE_COLOR:
+ return TrueColor;
+ case GLX_DIRECT_COLOR:
+ return DirectColor;
+ case GLX_PSEUDO_COLOR:
+ return PseudoColor;
+ case GLX_STATIC_COLOR:
+ return StaticColor;
+ case GLX_GRAY_SCALE:
+ return GrayScale;
+ case GLX_STATIC_GRAY:
+ return StaticGray;
+ case GLX_NONE:
+ default:
+ return None;
+ }
+}
+
+static GLboolean
+get_fbconfig_attribs(Display *dpy, GLXFBConfig fbconfig,
+ struct visual_attribs *attribs)
+{
+ int visual_type;
+
+ memset(attribs, 0, sizeof(struct visual_attribs));
+
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_FBCONFIG_ID, &attribs->id);
+
+#if 0
+ attribs->depth = vInfo->depth;
+ attribs->redMask = vInfo->red_mask;
+ attribs->greenMask = vInfo->green_mask;
+ attribs->blueMask = vInfo->blue_mask;
+ attribs->colormapSize = vInfo->colormap_size;
+ attribs->bitsPerRGB = vInfo->bits_per_rgb;
+#endif
+
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_X_VISUAL_TYPE, &visual_type);
+ attribs->klass = glx_token_to_visual_class(visual_type);
+
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_BUFFER_SIZE, &attribs->bufferSize);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_LEVEL, &attribs->level);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_RENDER_TYPE, &attribs->render_type);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_DOUBLEBUFFER, &attribs->doubleBuffer);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_STEREO, &attribs->stereo);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_AUX_BUFFERS, &attribs->auxBuffers);
+
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_RED_SIZE, &attribs->redSize);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_GREEN_SIZE, &attribs->greenSize);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_BLUE_SIZE, &attribs->blueSize);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_ALPHA_SIZE, &attribs->alphaSize);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_DEPTH_SIZE, &attribs->depthSize);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_STENCIL_SIZE, &attribs->stencilSize);
+
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize);
+
+ /* get transparent pixel stuff */
+ glXGetFBConfigAttrib(dpy, fbconfig,GLX_TRANSPARENT_TYPE, &attribs->transparentType);
+ if (attribs->transparentType == GLX_TRANSPARENT_RGB) {
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_RED_VALUE, &attribs->transparentRedValue);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_GREEN_VALUE, &attribs->transparentGreenValue);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_BLUE_VALUE, &attribs->transparentBlueValue);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_ALPHA_VALUE, &attribs->transparentAlphaValue);
+ }
+ else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) {
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue);
+ }
+
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLE_BUFFERS, &attribs->numMultisample);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLES, &attribs->numSamples);
+ glXGetFBConfigAttrib(dpy, fbconfig, GLX_CONFIG_CAVEAT, &attribs->visualCaveat);
+
+ return GL_TRUE;
+}
+
+#endif
+
+
static void
print_visual_attribs_verbose(const struct visual_attribs *attribs)
@@ -625,7 +775,8 @@ print_visual_attribs_verbose(const struct visual_attribs *attribs)
printf("Visual ID: %x depth=%d class=%s\n",
attribs->id, attribs->depth, visual_class_name(attribs->klass));
printf(" bufferSize=%d level=%d renderType=%s doubleBuffer=%d stereo=%d\n",
- attribs->bufferSize, attribs->level, attribs->rgba ? "rgba" : "ci",
+ attribs->bufferSize, attribs->level,
+ visual_render_type_name(attribs->render_type),
attribs->doubleBuffer, attribs->stereo);
printf(" rgba: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n",
attribs->redSize, attribs->greenSize,
@@ -683,16 +834,17 @@ print_visual_attribs_short(const struct visual_attribs *attribs)
caveat = "None";
#endif
- printf("0x%2x %2d %2s %2d %2d %2d %1s %2s %2s %2d %2d %2d %2d %2d %2d %2d",
+ printf("0x%02x %2d %2s %2d %2d %2d %c%c %c %c %2d %2d %2d %2d %2d %2d %2d",
attribs->id,
attribs->depth,
visual_class_abbrev(attribs->klass),
attribs->transparentType != GLX_NONE,
attribs->bufferSize,
attribs->level,
- attribs->rgba ? "r" : "c",
- attribs->doubleBuffer ? "y" : ".",
- attribs->stereo ? "y" : ".",
+ (attribs->render_type & GLX_RGBA_BIT) ? 'r' : ' ',
+ (attribs->render_type & GLX_COLOR_INDEX_BIT) ? 'c' : ' ',
+ attribs->doubleBuffer ? 'y' : '.',
+ attribs->stereo ? 'y' : '.',
attribs->redSize, attribs->greenSize,
attribs->blueSize, attribs->alphaSize,
attribs->auxBuffers,
@@ -728,7 +880,7 @@ print_visual_attribs_long(const struct visual_attribs *attribs)
attribs->transparentType != GLX_NONE,
attribs->bufferSize,
attribs->level,
- attribs->rgba ? "rgba" : "ci ",
+ visual_render_type_name(attribs->render_type),
attribs->doubleBuffer,
attribs->stereo,
attribs->redSize, attribs->greenSize,
@@ -751,42 +903,86 @@ print_visual_info(Display *dpy, int scrnum, InfoMode mode)
{
XVisualInfo theTemplate;
XVisualInfo *visuals;
- int numVisuals;
+ int numVisuals, numGlxVisuals;
long mask;
int i;
+ struct visual_attribs attribs;
/* get list of all visuals on this screen */
theTemplate.screen = scrnum;
mask = VisualScreenMask;
visuals = XGetVisualInfo(dpy, mask, &theTemplate, &numVisuals);
- if (mode == Verbose) {
- for (i = 0; i < numVisuals; i++) {
- struct visual_attribs attribs;
- get_visual_attribs(dpy, &visuals[i], &attribs);
- print_visual_attribs_verbose(&attribs);
- }
+ numGlxVisuals = 0;
+ for (i = 0; i < numVisuals; i++) {
+ if (get_visual_attribs(dpy, &visuals[i], &attribs))
+ numGlxVisuals++;
}
- else if (mode == Normal) {
+
+ if (numGlxVisuals == 0)
+ return;
+
+ printf("%d GLX Visuals\n", numGlxVisuals);
+
+ if (mode == Normal)
print_visual_attribs_short_header();
- for (i = 0; i < numVisuals; i++) {
- struct visual_attribs attribs;
- get_visual_attribs(dpy, &visuals[i], &attribs);
+ else if (mode == Wide)
+ print_visual_attribs_long_header();
+
+ for (i = 0; i < numVisuals; i++) {
+ if (!get_visual_attribs(dpy, &visuals[i], &attribs))
+ continue;
+
+ if (mode == Verbose)
+ print_visual_attribs_verbose(&attribs);
+ else if (mode == Normal)
print_visual_attribs_short(&attribs);
- }
+ else if (mode == Wide)
+ print_visual_attribs_long(&attribs);
}
- else if (mode == Wide) {
+ printf("\n");
+
+ XFree(visuals);
+}
+
+#ifdef GLX_VERSION_1_3
+
+static void
+print_fbconfig_info(Display *dpy, int scrnum, InfoMode mode)
+{
+ int numFBConfigs;
+ struct visual_attribs attribs;
+ GLXFBConfig *fbconfigs;
+ int i;
+
+ /* get list of all fbconfigs on this screen */
+ fbconfigs = glXGetFBConfigs(dpy, scrnum, &numFBConfigs);
+
+ if (numFBConfigs == 0)
+ return;
+
+ printf("%d GLXFBConfigs:\n", numFBConfigs);
+ if (mode == Normal)
+ print_visual_attribs_short_header();
+ else if (mode == Wide)
print_visual_attribs_long_header();
- for (i = 0; i < numVisuals; i++) {
- struct visual_attribs attribs;
- get_visual_attribs(dpy, &visuals[i], &attribs);
+
+ for (i = 0; i < numFBConfigs; i++) {
+ get_fbconfig_attribs(dpy, fbconfigs[i], &attribs);
+
+ if (mode == Verbose)
+ print_visual_attribs_verbose(&attribs);
+ else if (mode == Normal)
+ print_visual_attribs_short(&attribs);
+ else if (mode == Wide)
print_visual_attribs_long(&attribs);
- }
}
+ printf("\n");
- XFree(visuals);
+ XFree(fbconfigs);
}
+#endif
/*
* Stand-alone Mesa doesn't really implement the GLX protocol so it
@@ -860,7 +1056,7 @@ find_best_visual(Display *dpy, int scrnum)
/* see if this vis is better than bestVis */
if ((!bestVis.supportsGL && vis.supportsGL) ||
(bestVis.visualCaveat != GLX_NONE_EXT) ||
- (!bestVis.rgba && vis.rgba) ||
+ (!(bestVis.render_type & GLX_RGBA_BIT) && (vis.render_type & GLX_RGBA_BIT)) ||
(!bestVis.doubleBuffer && vis.doubleBuffer) ||
(bestVis.redSize < vis.redSize) ||
(bestVis.greenSize < vis.greenSize) ||
@@ -957,6 +1153,9 @@ main(int argc, char *argv[])
print_screen_info(dpy, scrnum, allowDirect, limits);
printf("\n");
print_visual_info(dpy, scrnum, mode);
+#ifdef GLX_VERSION_1_3
+ print_fbconfig_info(dpy, scrnum, mode);
+#endif
if (scrnum + 1 < numScreens)
printf("\n\n");
}
diff --git a/progs/xdemos/glxsnoop.c b/progs/xdemos/glxsnoop.c
new file mode 100644
index 00000000000..2e951345b58
--- /dev/null
+++ b/progs/xdemos/glxsnoop.c
@@ -0,0 +1,377 @@
+/**
+ * Display/snoop the z/stencil/back/front buffers of another app's window.
+ * Also, an example of the need for shared ancillary renderbuffers.
+ *
+ * Hint: use 'xwininfo' to get a window's ID.
+ *
+ * Brian Paul
+ * 11 Oct 2007
+ */
+
+#define GL_GLEXT_PROTOTYPES
+
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <X11/keysym.h>
+
+
+#define Z_BUFFER 1
+#define STENCIL_BUFFER 2
+#define BACK_BUFFER 3
+#define FRONT_BUFFER 4
+
+
+static int Buffer = BACK_BUFFER;
+static int WindowID = 0;
+static const char *DisplayName = NULL;
+static GLXContext Context = 0;
+static int Width, Height;
+
+
+/**
+ * Grab the z/stencil/back/front image from the srcWin and display it
+ * (possibly converted to grayscale) in the dstWin.
+ */
+static void
+redraw(Display *dpy, Window srcWin, Window dstWin )
+{
+ GLubyte *image = malloc(Width * Height * 4);
+
+ glXMakeCurrent(dpy, srcWin, Context);
+ glPixelStorei(GL_PACK_ALIGNMENT, 1);
+ if (Buffer == BACK_BUFFER) {
+ glReadBuffer(GL_BACK);
+ glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, image);
+ }
+ else if (Buffer == FRONT_BUFFER) {
+ glReadBuffer(GL_FRONT);
+ glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, image);
+ }
+ else if (Buffer == Z_BUFFER) {
+ GLfloat *z = malloc(Width * Height * sizeof(GLfloat));
+ int i;
+ glReadPixels(0, 0, Width, Height, GL_DEPTH_COMPONENT, GL_FLOAT, z);
+ for (i = 0; i < Width * Height; i++) {
+ image[i*4+0] =
+ image[i*4+1] =
+ image[i*4+2] = (GLint) (255.0 * z[i]);
+ image[i*4+3] = 255;
+ }
+ free(z);
+ }
+ else if (Buffer == STENCIL_BUFFER) {
+ GLubyte *sten = malloc(Width * Height * sizeof(GLubyte));
+ int i, min = 100, max = -1;
+ float step;
+ int sz;
+ glGetIntegerv(GL_STENCIL_BITS, &sz);
+ glReadPixels(0, 0, Width, Height,
+ GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, sten);
+ /* find min/max for converting stencil to grayscale */
+ for (i = 0; i < Width * Height; i++) {
+ if (sten[i] < min)
+ min = sten[i];
+ if (sten[i] > max)
+ max = sten[i];
+ }
+ if (min == max)
+ step = 0;
+ else
+ step = 255.0 / (float) (max - min);
+ for (i = 0; i < Width * Height; i++) {
+ image[i*4+0] =
+ image[i*4+1] =
+ image[i*4+2] = (GLint) ((sten[i] - min) * step);
+ image[i*4+3] = 255;
+ }
+ free(sten);
+ }
+
+ glXMakeCurrent(dpy, dstWin, Context);
+ glWindowPos2iARB(0, 0);
+ glDrawBuffer(GL_FRONT);
+ glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, image);
+ glFlush();
+
+ free(image);
+}
+
+
+static void
+set_window_title(Display *dpy, Window win, const char *title)
+{
+ XSizeHints sizehints;
+ sizehints.flags = 0;
+ XSetStandardProperties(dpy, win, title, title,
+ None, (char **)NULL, 0, &sizehints);
+}
+
+
+static Window
+make_gl_window(Display *dpy, XVisualInfo *visinfo, int width, int height)
+{
+ int scrnum;
+ XSetWindowAttributes attr;
+ unsigned long mask;
+ Window root;
+ Window win;
+ int x = 0, y = 0;
+ char *name = NULL;
+
+ scrnum = DefaultScreen( dpy );
+ root = RootWindow( dpy, scrnum );
+
+ /* window attributes */
+ attr.background_pixel = 0;
+ attr.border_pixel = 0;
+ attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
+ attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
+ mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+ win = XCreateWindow( dpy, root, x, y, width, height,
+ 0, visinfo->depth, InputOutput,
+ visinfo->visual, mask, &attr );
+
+ /* set hints and properties */
+ {
+ XSizeHints sizehints;
+ sizehints.x = x;
+ sizehints.y = y;
+ sizehints.width = width;
+ sizehints.height = height;
+ sizehints.flags = USSize | USPosition;
+ XSetNormalHints(dpy, win, &sizehints);
+ XSetStandardProperties(dpy, win, name, name,
+ None, (char **)NULL, 0, &sizehints);
+ }
+
+ return win;
+}
+
+
+static void
+update_window_title(Display *dpy, Window win)
+{
+ char title[1000], *buf;
+
+ switch (Buffer) {
+ case Z_BUFFER:
+ buf = "Z";
+ break;
+ case STENCIL_BUFFER:
+ buf = "Stencil";
+ break;
+ case BACK_BUFFER:
+ buf = "Back";
+ break;
+ case FRONT_BUFFER:
+ buf = "Front";
+ break;
+ default:
+ buf = "";
+ }
+
+ sprintf(title, "glxsnoop window 0x%x (%s buffer)", (int) WindowID, buf);
+
+ set_window_title(dpy, win, title);
+}
+
+
+static void
+keypress(Display *dpy, Window win, char key)
+{
+ switch (key) {
+ case 27:
+ /* escape */
+ exit(0);
+ break;
+ case 's':
+ Buffer = STENCIL_BUFFER;
+ break;
+ case 'z':
+ Buffer = Z_BUFFER;
+ break;
+ case 'f':
+ Buffer = FRONT_BUFFER;
+ break;
+ case 'b':
+ Buffer = BACK_BUFFER;
+ break;
+ default:
+ return;
+ }
+
+ update_window_title(dpy, win);
+ redraw(dpy, WindowID, win);
+}
+
+
+static void
+event_loop(Display *dpy, Window win)
+{
+ XEvent event;
+
+ while (1) {
+ XNextEvent( dpy, &event );
+
+ switch (event.type) {
+ case Expose:
+ redraw(dpy, WindowID, win);
+ break;
+ case ConfigureNotify:
+ /*resize( event.xconfigure.width, event.xconfigure.height );*/
+ break;
+ case KeyPress:
+ {
+ char buffer[10];
+ int r, code;
+ code = XLookupKeysym(&event.xkey, 0);
+ if (code == XK_Left) {
+ }
+ else {
+ r = XLookupString(&event.xkey, buffer, sizeof(buffer),
+ NULL, NULL);
+ keypress(dpy, win, buffer[0]);
+ }
+ }
+ default:
+ /* nothing */
+ ;
+ }
+ }
+}
+
+
+static VisualID
+get_window_visualid(Display *dpy, Window win)
+{
+ XWindowAttributes attr;
+
+ if (XGetWindowAttributes(dpy, win, &attr)) {
+ return attr.visual->visualid;
+ }
+ else {
+ return 0;
+ }
+}
+
+
+static void
+get_window_size(Display *dpy, Window win, int *w, int *h)
+{
+ XWindowAttributes attr;
+
+ if (XGetWindowAttributes(dpy, win, &attr)) {
+ *w = attr.width;
+ *h = attr.height;
+ }
+ else {
+ *w = *h = 0;
+ }
+}
+
+
+static XVisualInfo *
+visualid_to_visualinfo(Display *dpy, VisualID vid)
+{
+ XVisualInfo *vinfo, templ;
+ long mask;
+ int n;
+
+ templ.visualid = vid;
+ mask = VisualIDMask;
+
+ vinfo = XGetVisualInfo(dpy, mask, &templ, &n);
+ return vinfo;
+}
+
+
+static void
+key_usage(void)
+{
+ printf("Keyboard:\n");
+ printf(" z - display Z buffer\n");
+ printf(" s - display stencil buffer\n");
+ printf(" f - display front color buffer\n");
+ printf(" b - display back buffer\n");
+}
+
+
+static void
+usage(void)
+{
+ printf("Usage: glxsnoop [-display dpy] windowID\n");
+ key_usage();
+}
+
+
+static void
+parse_opts(int argc, char *argv[])
+{
+ int i;
+
+ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-h") == 0) {
+ usage();
+ exit(0);
+ }
+ else if (strcmp(argv[i], "-display") == 0) {
+ DisplayName = argv[i + 1];
+ i++;
+ }
+ else {
+ if (argv[i][0] == '0' && argv[i][1] == 'x') {
+ /* hex */
+ WindowID = strtol(argv[i], NULL, 16);
+ }
+ else {
+ WindowID = atoi(argv[i]);
+ }
+ break;
+ }
+ }
+
+ if (!WindowID) {
+ usage();
+ exit(0);
+ }
+}
+
+
+int
+main( int argc, char *argv[] )
+{
+ Display *dpy;
+ VisualID vid;
+ XVisualInfo *visinfo;
+ Window win;
+
+ parse_opts(argc, argv);
+
+ key_usage();
+
+ dpy = XOpenDisplay(DisplayName);
+
+ /* find the VisualID for the named window */
+ vid = get_window_visualid(dpy, WindowID);
+ get_window_size(dpy, WindowID, &Width, &Height);
+
+ visinfo = visualid_to_visualinfo(dpy, vid);
+
+ Context = glXCreateContext( dpy, visinfo, NULL, True );
+ if (!Context) {
+ printf("Error: glXCreateContext failed\n");
+ exit(1);
+ }
+
+ win = make_gl_window(dpy, visinfo, Width, Height);
+ XMapWindow(dpy, win);
+ update_window_title(dpy, win);
+
+ event_loop( dpy, win );
+
+ return 0;
+}
diff --git a/progs/xdemos/glxswapcontrol.c b/progs/xdemos/glxswapcontrol.c
index d9be984be57..e429d58ecc4 100644
--- a/progs/xdemos/glxswapcontrol.c
+++ b/progs/xdemos/glxswapcontrol.c
@@ -814,6 +814,11 @@ main(int argc, char *argv[])
init();
+ /* Set initial projection/viewing transformation.
+ * same as glxgears.c
+ */
+ reshape(300, 300);
+
event_loop(dpy, win);
glXDestroyContext(dpy, ctx);
diff --git a/progs/xdemos/ipc.c b/progs/xdemos/ipc.c
new file mode 100644
index 00000000000..c872d1641ab
--- /dev/null
+++ b/progs/xdemos/ipc.c
@@ -0,0 +1,264 @@
+/* Copyright (c) 2003 Tungsten Graphics, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files ("the
+ * Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions: The above copyright notice, the Tungsten
+ * Graphics splash screen, and this permission notice shall be included
+ * in all copies or substantial portions of the Software. THE SOFTWARE
+ * IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+ * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Simple IPC API
+ * Brian Paul
+ */
+
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include "ipc.h"
+
+#if defined(IRIX) || defined(irix)
+typedef int socklen_t;
+#endif
+
+#define NO_DELAY 1
+
+#define DEFAULT_MASTER_PORT 7011
+
+
+/*
+ * Return my hostname in <nameOut>.
+ * Return 1 for success, 0 for error.
+ */
+int
+MyHostName(char *nameOut, int maxNameLength)
+{
+ int k = gethostname(nameOut, maxNameLength);
+ return k==0;
+}
+
+
+/*
+ * Create a socket attached to a port. Later, we can call AcceptConnection
+ * on the socket returned from this function.
+ * Return the new socket number or -1 if error.
+ */
+int
+CreatePort(int *port)
+{
+ char hostname[1000];
+ struct sockaddr_in servaddr;
+ struct hostent *hp;
+ int so_reuseaddr = 1;
+ int tcp_nodelay = 1;
+ int sock, k;
+
+ /* create socket */
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ assert(sock > 2);
+
+ /* get my host name */
+ k = gethostname(hostname, 1000);
+ assert(k == 0);
+
+ /* get hostent info */
+ hp = gethostbyname(hostname);
+ assert(hp);
+
+ /* initialize the servaddr struct */
+ memset(&servaddr, 0, sizeof(servaddr) );
+ servaddr.sin_family = AF_INET;
+ servaddr.sin_port = htons((unsigned short) (*port));
+ memcpy((char *) &servaddr.sin_addr, hp->h_addr,
+ sizeof(servaddr.sin_addr));
+
+ /* deallocate when we exit */
+ k = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+ (char *) &so_reuseaddr, sizeof(so_reuseaddr));
+ assert(k==0);
+
+ /* send packets immediately */
+#if NO_DELAY
+ k = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
+ (char *) &tcp_nodelay, sizeof(tcp_nodelay));
+ assert(k==0);
+#endif
+
+ if (*port == 0)
+ *port = DEFAULT_MASTER_PORT;
+
+ k = 1;
+ while (k && (*port < 65534)) {
+ /* bind our address to the socket */
+ servaddr.sin_port = htons((unsigned short) (*port));
+ k = bind(sock, (struct sockaddr *) &servaddr, sizeof(servaddr));
+ if (k)
+ *port = *port + 1;
+ }
+
+#if 0
+ printf("###### Real Port: %d\n", *port);
+#endif
+
+ /* listen for connections */
+ k = listen(sock, 100);
+ assert(k == 0);
+
+ return sock;
+}
+
+
+/*
+ * Accept a connection on the named socket.
+ * Return a new socket for the new connection, or -1 if error.
+ */
+int
+AcceptConnection(int socket)
+{
+ struct sockaddr addr;
+ socklen_t addrLen;
+ int newSock;
+
+ addrLen = sizeof(addr);
+ newSock = accept(socket, &addr, &addrLen);
+ if (newSock == 1)
+ return -1;
+ else
+ return newSock;
+}
+
+
+/*
+ * Contact the server running on the given host on the named port.
+ * Return socket number or -1 if error.
+ */
+int
+Connect(const char *hostname, int port)
+{
+ struct sockaddr_in servaddr;
+ struct hostent *hp;
+ int sock, k;
+ int tcp_nodelay = 1;
+
+ assert(port);
+
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ assert(sock >= 0);
+
+ hp = gethostbyname(hostname);
+ assert(hp);
+
+ memset(&servaddr, 0, sizeof(servaddr));
+ servaddr.sin_family = AF_INET;
+ servaddr.sin_port = htons((unsigned short) port);
+ memcpy((char *) &servaddr.sin_addr, hp->h_addr, sizeof(servaddr.sin_addr));
+
+ k = connect(sock, (struct sockaddr *) &servaddr, sizeof(servaddr));
+ if (k != 0) {
+ perror("Connect:");
+ return -1;
+ }
+
+#if NO_DELAY
+ /* send packets immediately */
+ k = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
+ (char *) &tcp_nodelay, sizeof(tcp_nodelay));
+ assert(k==0);
+#endif
+
+ return sock;
+}
+
+
+void
+CloseSocket(int socket)
+{
+ close(socket);
+}
+
+
+int
+SendData(int socket, const void *data, int bytes)
+{
+ int sent = 0;
+ int b;
+
+ while (sent < bytes) {
+ b = write(socket, (char *) data + sent, bytes - sent);
+ if (b <= 0)
+ return -1; /* something broke */
+ sent += b;
+ }
+ return sent;
+}
+
+
+int
+ReceiveData(int socket, void *data, int bytes)
+{
+ int received = 0, b;
+
+ while (received < bytes) {
+ b = read(socket, (char *) data + received, bytes - received);
+ if (b <= 0)
+ return -1;
+ received += b;
+ }
+ return received;
+}
+
+
+int
+SendString(int socket, const char *str)
+{
+ const int len = strlen(str);
+ int sent, b;
+
+ /* first, send a 4-byte length indicator */
+ b = write(socket, &len, sizeof(len));
+ if (b <= 0)
+ return -1;
+
+ sent = SendData(socket, str, len);
+ assert(sent == len);
+ return sent;
+}
+
+
+int
+ReceiveString(int socket, char *str, int maxLen)
+{
+ int len, received, b;
+
+ /* first, read 4 bytes to see how long of string to receive */
+ b = read(socket, &len, sizeof(len));
+ if (b <= 0)
+ return -1;
+
+ assert(len <= maxLen); /* XXX fix someday */
+ assert(len >= 0);
+ received = ReceiveData(socket, str, len);
+ assert(received != -1);
+ assert(received == len);
+ str[len] = 0;
+ return received;
+}
diff --git a/progs/xdemos/ipc.h b/progs/xdemos/ipc.h
new file mode 100644
index 00000000000..3f434457c6f
--- /dev/null
+++ b/progs/xdemos/ipc.h
@@ -0,0 +1,16 @@
+#ifndef IPC_H
+#define IPC_H
+
+
+extern int MyHostName(char *nameOut, int maxNameLength);
+extern int CreatePort(int *port);
+extern int AcceptConnection(int socket);
+extern int Connect(const char *hostname, int port);
+extern void CloseSocket(int socket);
+extern int SendData(int socket, const void *data, int bytes);
+extern int ReceiveData(int socket, void *data, int bytes);
+extern int SendString(int socket, const char *str);
+extern int ReceiveString(int socket, char *str, int maxLen);
+
+
+#endif /* IPC_H */
diff --git a/progs/xdemos/offset.c b/progs/xdemos/offset.c
index 97170f5c8de..6c5abf383be 100644
--- a/progs/xdemos/offset.c
+++ b/progs/xdemos/offset.c
@@ -70,12 +70,12 @@ typedef Vertex Quad[4];
/* data to define the six faces of a unit cube */
Quad quads[MAXQUAD] = {
- { {0,0,0}, {1,0,0}, {1,1,0}, {0,1,0} },
- { {0,0,1}, {1,0,1}, {1,1,1}, {0,1,1} },
- { {0,0,0}, {1,0,0}, {1,0,1}, {0,0,1} },
- { {0,1,0}, {1,1,0}, {1,1,1}, {0,1,1} },
- { {0,0,0}, {0,0,1}, {0,1,1}, {0,1,0} },
- { {1,0,0}, {1,0,1}, {1,1,1}, {1,1,0} }
+ { {0,0,0}, {0,0,1}, {0,1,1}, {0,1,0} }, /* x = 0 */
+ { {0,0,0}, {1,0,0}, {1,0,1}, {0,0,1} }, /* y = 0 */
+ { {0,0,0}, {1,0,0}, {1,1,0}, {0,1,0} }, /* z = 0 */
+ { {1,0,0}, {1,0,1}, {1,1,1}, {1,1,0} }, /* x = 1 */
+ { {0,1,0}, {1,1,0}, {1,1,1}, {0,1,1} }, /* y = 1 */
+ { {0,0,1}, {1,0,1}, {1,1,1}, {0,1,1} } /* z = 1 */
};
#define WIREFRAME 0
@@ -85,7 +85,7 @@ static void error(const char* prog, const char* msg);
static void cubes(int mx, int my, int mode);
static void fill(Quad quad);
static void outline(Quad quad);
-static void draw_hidden(Quad quad, int mode);
+static void draw_hidden(Quad quad, int mode, int face);
static void process_input(Display *dpy, Window win);
static int query_extension(char* extName);
@@ -100,6 +100,7 @@ int main(int argc, char** argv) {
XSetWindowAttributes swa;
Window win;
GLXContext cx;
+ GLint z;
dpy = XOpenDisplay(0);
if (!dpy) error(argv[0], "can't open display");
@@ -140,6 +141,9 @@ int main(int argc, char** argv) {
/* set other relevant state information */
glEnable(GL_DEPTH_TEST);
+ glGetIntegerv(GL_DEPTH_BITS, &z);
+ printf("GL_DEPTH_BITS = %d\n", z);
+
#ifdef GL_EXT_polygon_offset
printf("using 1.0 offset extension\n");
glPolygonOffsetEXT( 1.0, 0.00001 );
@@ -159,6 +163,7 @@ int main(int argc, char** argv) {
static void
draw_scene(int mx, int my) {
+ glClearColor(0.25, 0.25, 0.25, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
@@ -205,7 +210,7 @@ cubes(int mx, int my, int mode) {
glTranslatef(x, y, z);
glScalef(0.8, 0.8, 0.8);
for (i = 0; i < MAXQUAD; i++)
- draw_hidden(quads[i], mode);
+ draw_hidden(quads[i], mode, i);
glPopMatrix();
}
}
@@ -235,13 +240,18 @@ outline(Quad quad) {
}
static void
-draw_hidden(Quad quad, int mode) {
+draw_hidden(Quad quad, int mode, int face) {
+ static const GLfloat colors[3][3] = {
+ {0.5, 0.5, 0.0},
+ {0.8, 0.5, 0.0},
+ {0.0, 0.5, 0.8}
+ };
if (mode == HIDDEN_LINE) {
- glColor3f(0, 0, 0);
+ glColor3fv(colors[face % 3]);
fill(quad);
}
- /* draw the outline using white, optionally fill the interior with black */
+ /* draw the outline using white */
glColor3f(1, 1, 1);
outline(quad);
}
diff --git a/progs/xdemos/pbutil.c b/progs/xdemos/pbutil.c
index d0bbd1b0fce..ce133d012dc 100644
--- a/progs/xdemos/pbutil.c
+++ b/progs/xdemos/pbutil.c
@@ -18,12 +18,12 @@
* Test if we pixel buffers are available for a particular X screen.
* Input: dpy - the X display
* screen - screen number
- * Return: 0 = pixel buffers not available.
- * 1 = pixel buffers are available via GLX 1.3.
- * 2 = pixel buffers are available via GLX_SGIX_fbconfig/pbuffer.
+ * Return: 0 = fbconfigs not available.
+ * 1 = fbconfigs are available via GLX 1.3.
+ * 2 = fbconfigs and pbuffers are available via GLX_SGIX_fbconfig
*/
int
-QueryPbuffers(Display *dpy, int screen)
+QueryFBConfig(Display *dpy, int screen)
{
#if defined(GLX_VERSION_1_3)
{
@@ -40,36 +40,55 @@ QueryPbuffers(Display *dpy, int screen)
}
#endif
-#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
/* Try the SGIX extensions */
{
char *extensions;
extensions = (char *) glXQueryServerString(dpy, screen, GLX_EXTENSIONS);
- if (!extensions ||
- !strstr(extensions,"GLX_SGIX_fbconfig") ||
- !strstr(extensions,"GLX_SGIX_pbuffer")) {
- return 0;
+ if (extensions && strstr(extensions,"GLX_SGIX_fbconfig")) {
+ return 2;
}
- return 2;
}
-#endif
return 0;
}
+/**
+ * Test if we pixel buffers are available for a particular X screen.
+ * Input: dpy - the X display
+ * screen - screen number
+ * Return: 0 = pixel buffers not available.
+ * 1 = pixel buffers are available via GLX 1.3.
+ * 2 = pixel buffers are available via GLX_SGIX_fbconfig/pbuffer.
+ */
+int
+QueryPbuffers(Display *dpy, int screen)
+{
+ int ret;
+ ret = QueryFBConfig(dpy, screen);
+ if (ret == 2) {
+ char *extensions;
+ extensions = (char *) glXQueryServerString(dpy, screen, GLX_EXTENSIONS);
+ if (extensions && strstr(extensions, "GLX_SGIX_pbuffer"))
+ return 2;
+ else
+ return 0;
+ }
+ else
+ return ret;
+}
FBCONFIG *
ChooseFBConfig(Display *dpy, int screen, const int attribs[], int *nConfigs)
{
- int pbSupport = QueryPbuffers(dpy, screen);
+ int fbcSupport = QueryPbuffers(dpy, screen);
#if defined(GLX_VERSION_1_3)
- if (pbSupport == 1) {
+ if (fbcSupport == 1) {
return glXChooseFBConfig(dpy, screen, attribs, nConfigs);
}
#endif
#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
- if (pbSupport == 2) {
+ if (fbcSupport == 2) {
return glXChooseFBConfigSGIX(dpy, screen, (int *) attribs, nConfigs);
}
#endif
@@ -80,14 +99,14 @@ ChooseFBConfig(Display *dpy, int screen, const int attribs[], int *nConfigs)
FBCONFIG *
GetAllFBConfigs(Display *dpy, int screen, int *nConfigs)
{
- int pbSupport = QueryPbuffers(dpy, screen);
+ int fbcSupport = QueryFBConfig(dpy, screen);
#if defined(GLX_VERSION_1_3)
- if (pbSupport == 1) {
+ if (fbcSupport == 1) {
return glXGetFBConfigs(dpy, screen, nConfigs);
}
#endif
#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
- if (pbSupport == 2) {
+ if (fbcSupport == 2) {
/* The GLX_SGIX_fbconfig extensions says to pass NULL to get list
* of all available configurations.
*/
@@ -101,14 +120,14 @@ GetAllFBConfigs(Display *dpy, int screen, int *nConfigs)
XVisualInfo *
GetVisualFromFBConfig(Display *dpy, int screen, FBCONFIG config)
{
- int pbSupport = QueryPbuffers(dpy, screen);
+ int fbcSupport = QueryFBConfig(dpy, screen);
#if defined(GLX_VERSION_1_3)
- if (pbSupport == 1) {
+ if (fbcSupport == 1) {
return glXGetVisualFromFBConfig(dpy, config);
}
#endif
#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
- if (pbSupport == 2) {
+ if (fbcSupport == 2) {
return glXGetVisualFromFBConfigSGIX(dpy, config);
}
#endif
@@ -130,11 +149,11 @@ GetFBConfigAttrib(Display *dpy, int screen,
int attrib
)
{
- int pbSupport = QueryPbuffers(dpy, screen);
+ int fbcSupport = QueryFBConfig(dpy, screen);
int value = 0;
#if defined(GLX_VERSION_1_3)
- if (pbSupport == 1) {
+ if (fbcSupport == 1) {
/* ok */
if (glXGetFBConfigAttrib(dpy, config, attrib, &value) != 0) {
value = 0;
@@ -145,7 +164,7 @@ GetFBConfigAttrib(Display *dpy, int screen,
#endif
#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
- if (pbSupport == 2) {
+ if (fbcSupport == 2) {
if (glXGetFBConfigAttribSGIX(dpy, config, attrib, &value) != 0) {
value = 0;
}
@@ -295,9 +314,9 @@ PrintFBConfigInfo(Display *dpy, int screen, FBCONFIG config, Bool horizFormat)
GLXContext
CreateContext(Display *dpy, int screen, FBCONFIG config)
{
- int pbSupport = QueryPbuffers(dpy, screen);
+ int fbcSupport = QueryFBConfig(dpy, screen);
#if defined(GLX_VERSION_1_3)
- if (pbSupport == 1) {
+ if (fbcSupport == 1) {
/* GLX 1.3 */
GLXContext c;
c = glXCreateNewContext(dpy, config, GLX_RGBA_TYPE, NULL, True);
@@ -309,7 +328,7 @@ CreateContext(Display *dpy, int screen, FBCONFIG config)
}
#endif
#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer)
- if (pbSupport == 2) {
+ if (fbcSupport == 2) {
GLXContext c;
c = glXCreateContextWithConfigSGIX(dpy, config, GLX_RGBA_TYPE_SGIX, NULL, True);
if (!c) {
@@ -393,6 +412,7 @@ CreatePbuffer(Display *dpy, int screen, FBCONFIG config,
pBuffer = None;
}
+ XSync(dpy, False);
/* Restore original X error handler */
(void) XSetErrorHandler(oldHandler);
diff --git a/progs/xdemos/pbutil.h b/progs/xdemos/pbutil.h
index e95b2565a23..d420522ff01 100644
--- a/progs/xdemos/pbutil.h
+++ b/progs/xdemos/pbutil.h
@@ -27,6 +27,9 @@
extern int
+QueryFBConfig(Display *dpy, int screen);
+
+extern int
QueryPbuffers(Display *dpy, int screen);
diff --git a/progs/xdemos/sharedtex.c b/progs/xdemos/sharedtex.c
new file mode 100644
index 00000000000..81703fe0e7d
--- /dev/null
+++ b/progs/xdemos/sharedtex.c
@@ -0,0 +1,324 @@
+/*
+ * Test sharing of texture objects by two rendering contexts.
+ * In particular, test that changing a texture object in one context
+ * effects the texture in the second context.
+ *
+ * Brian Paul
+ * 30 Apr 2008
+ *
+ * Copyright (C) 2008 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.
+ */
+
+
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <X11/keysym.h>
+
+
+#define MAX_CONTEXTS 2
+
+#define TEX_SIZE 32
+
+static const char *DisplayName = NULL;
+static Display *Dpy;
+static XVisualInfo *VisInfo;
+static Window Win;
+static GLXContext Contexts[MAX_CONTEXTS];
+static int WinWidth = 300, WinHeight = 300;
+
+static int DrawContext = 0, TexContext = 1;
+
+static GLuint TexObj = 0;
+static GLboolean NewTexture = GL_FALSE;
+
+
+static void
+Error(const char *msg)
+{
+ fprintf(stderr, "sharedtex error: %s\n", msg);
+ exit(1);
+}
+
+
+static void
+CreateWindow(const char *name)
+{
+ int attrib[] = { GLX_RGBA,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_DOUBLEBUFFER,
+ None };
+ int scrnum;
+ XSetWindowAttributes attr;
+ unsigned long mask;
+ Window root;
+ int xpos = 0, ypos = 0;
+ static int n = 0;
+
+ scrnum = DefaultScreen(Dpy);
+ root = RootWindow(Dpy, scrnum);
+
+ VisInfo = glXChooseVisual(Dpy, scrnum, attrib);
+ if (!VisInfo) {
+ Error("Unable to find RGB, double-buffered visual");
+ }
+
+ /* window attributes */
+ xpos = (n % 10) * 100;
+ ypos = (n / 10) * 100;
+ n++;
+
+ 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, xpos, ypos, WinWidth, WinHeight,
+ 0, VisInfo->depth, InputOutput,
+ VisInfo->visual, mask, &attr);
+ if (!Win) {
+ Error("Couldn't create window");
+ }
+
+ {
+ XSizeHints sizehints;
+ sizehints.x = xpos;
+ sizehints.y = ypos;
+ sizehints.width = WinWidth;
+ sizehints.height = WinHeight;
+ sizehints.flags = USSize | USPosition;
+ XSetNormalHints(Dpy, Win, &sizehints);
+ XSetStandardProperties(Dpy, Win, name, name,
+ None, (char **)NULL, 0, &sizehints);
+ }
+
+ XMapWindow(Dpy, Win);
+}
+
+
+/**
+ * Change texture image, using TexContext
+ */
+static void
+ModifyTexture(void)
+{
+ GLuint tex[TEX_SIZE][TEX_SIZE];
+ GLuint c0, c1;
+ int i, j;
+
+ if (Win && !glXMakeCurrent(Dpy, Win, Contexts[TexContext])) {
+ Error("glXMakeCurrent failed");
+ }
+
+ /* choose two random colors */
+ c0 = rand() & 0xffffffff;
+ c1 = rand() & 0xffffffff;
+
+ for (i = 0; i < TEX_SIZE; i++) {
+ for (j = 0; j < TEX_SIZE; j++) {
+ if (((i / 4) ^ (j / 4)) & 1) {
+ tex[i][j] = c0;
+ }
+ else {
+ tex[i][j] = c1;
+ }
+ }
+ }
+
+ glBindTexture(GL_TEXTURE_2D, TexObj);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEX_SIZE, TEX_SIZE, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, tex);
+
+ NewTexture = GL_TRUE;
+}
+
+
+static void
+InitContext(void)
+{
+ glGenTextures(1, &TexObj);
+ assert(TexObj);
+ glBindTexture(GL_TEXTURE_2D, TexObj);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glEnable(GL_TEXTURE_2D);
+
+ printf("GL_RENDERER = %s\n", (char*) glGetString(GL_RENDERER));
+}
+
+
+static void
+Setup(void)
+{
+ int i;
+
+ Dpy = XOpenDisplay(DisplayName);
+ if (!Dpy) {
+ Error("Unable to open display");
+ }
+
+ CreateWindow("sharedtex");
+
+ for (i = 0; i < MAX_CONTEXTS; i++) {
+ GLXContext share = i > 0 ? Contexts[0] : 0;
+
+ Contexts[i] = glXCreateContext(Dpy, VisInfo, share, True);
+ if (!Contexts[i]) {
+ Error("Unable to create GLX context");
+ }
+
+ if (!glXMakeCurrent(Dpy, Win, Contexts[i])) {
+ Error("glXMakeCurrent failed");
+ }
+
+ InitContext();
+ }
+
+ ModifyTexture();
+}
+
+
+/**
+ * Redraw window, using DrawContext
+ */
+static void
+Redraw(void)
+{
+ static float rot = 0.0;
+ float ar;
+
+ rot += 1.0;
+
+ if (Win && !glXMakeCurrent(Dpy, Win, Contexts[DrawContext])) {
+ Error("glXMakeCurrent failed");
+ }
+
+ glViewport(0, 0, WinWidth, WinHeight);
+ ar = (float) WinWidth / (float) WinHeight;
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(-ar, ar, -1.0, 1.0, -1.0, 1.0);
+ glMatrixMode(GL_MODELVIEW);
+
+ glShadeModel(GL_FLAT);
+ glClearColor(0.5, 0.5, 0.5, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glPushMatrix();
+ glRotatef(rot, 0, 0, 1);
+ glScalef(0.7, 0.7, 0.7);
+
+ if (NewTexture) {
+ /* rebind to get new contents */
+ glBindTexture(GL_TEXTURE_2D, TexObj);
+ NewTexture = GL_FALSE;
+ }
+
+ /* draw textured quad */
+ glBegin(GL_POLYGON);
+ glTexCoord2f( 0.0, 0.0 ); glVertex2f( -1.0, -1.0 );
+ glTexCoord2f( 1.0, 0.0 ); glVertex2f( 1.0, -1.0 );
+ glTexCoord2f( 1.0, 1.0 ); glVertex2f( 1.0, 1.0 );
+ glTexCoord2f( 0.0, 1.0 ); glVertex2f( -1.0, 1.0 );
+ glEnd();
+
+ glPopMatrix();
+
+ if (Win)
+ glXSwapBuffers(Dpy, Win);
+}
+
+
+static void
+EventLoop(void)
+{
+ while (1) {
+ while (XPending(Dpy) > 0) {
+ XEvent event;
+ XNextEvent(Dpy, &event);
+
+ switch (event.type) {
+ case Expose:
+ Redraw();
+ break;
+ case ConfigureNotify:
+ WinWidth = event.xconfigure.width;
+ WinHeight = event.xconfigure.height;
+ break;
+ case KeyPress:
+ {
+ char buf[100];
+ KeySym keySym;
+ XComposeStatus stat;
+ XLookupString(&event.xkey, buf, sizeof(buf), &keySym, &stat);
+ switch (keySym) {
+ case XK_Escape:
+ exit(0);
+ break;
+ case XK_t:
+ case XK_T:
+ ModifyTexture();
+ break;
+ default:
+ ;
+ }
+ }
+ Redraw();
+ break;
+ default:
+ /*no-op*/ ;
+ }
+ }
+
+ Redraw();
+ usleep(10000);
+ }
+}
+
+
+
+
+int
+main(int argc, char *argv[])
+{
+ int i;
+
+ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-display") == 0 && i < argc) {
+ DisplayName = argv[i+1];
+ i++;
+ }
+ }
+
+ Setup();
+
+ printf("Press 't' to change texture image/colors\n");
+
+ EventLoop();
+
+ return 0;
+}
diff --git a/progs/xdemos/texture_from_pixmap.c b/progs/xdemos/texture_from_pixmap.c
new file mode 100644
index 00000000000..ab215b0ac30
--- /dev/null
+++ b/progs/xdemos/texture_from_pixmap.c
@@ -0,0 +1,396 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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.
+ */
+
+
+/*
+ * Test the GLX_EXT_texture_from_pixmap extension
+ * Brian Paul
+ * 19 May 2007
+ */
+
+
+#define GL_GLEXT_PROTOTYPES
+#define GLX_GLXEXT_PROTOTYPES
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <X11/keysym.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+static float top, bottom;
+
+static PFNGLXBINDTEXIMAGEEXTPROC glXBindTexImageEXT_func = NULL;
+static PFNGLXRELEASETEXIMAGEEXTPROC glXReleaseTexImageEXT_func = NULL;
+
+
+static Display *
+OpenDisplay(void)
+{
+ int screen;
+ Display *dpy;
+ const char *ext;
+
+ dpy = XOpenDisplay(NULL);
+ if (!dpy) {
+ printf("Couldn't open default display!\n");
+ exit(1);
+ }
+
+ screen = DefaultScreen(dpy);
+ ext = glXQueryExtensionsString(dpy, screen);
+ if (!strstr(ext, "GLX_EXT_texture_from_pixmap")) {
+ fprintf(stderr, "GLX_EXT_texture_from_pixmap not supported.\n");
+ exit(1);
+ }
+
+ glXBindTexImageEXT_func = (PFNGLXBINDTEXIMAGEEXTPROC)
+ glXGetProcAddress((GLubyte *) "glXBindTexImageEXT");
+ glXReleaseTexImageEXT_func = (PFNGLXRELEASETEXIMAGEEXTPROC)
+ glXGetProcAddress((GLubyte*) "glXReleaseTexImageEXT");
+
+ if (!glXBindTexImageEXT_func || !glXReleaseTexImageEXT_func) {
+ fprintf(stderr, "glXGetProcAddress failed!\n");
+ exit(1);
+ }
+
+ return dpy;
+}
+
+
+static GLXFBConfig
+ChoosePixmapFBConfig(Display *display)
+{
+ int screen = DefaultScreen(display);
+ GLXFBConfig *fbconfigs;
+ int i, nfbconfigs, value;
+
+ fbconfigs = glXGetFBConfigs(display, screen, &nfbconfigs);
+ for (i = 0; i < nfbconfigs; i++) {
+
+ glXGetFBConfigAttrib(display, fbconfigs[i], GLX_DRAWABLE_TYPE, &value);
+ if (!(value & GLX_PIXMAP_BIT))
+ continue;
+
+ glXGetFBConfigAttrib(display, fbconfigs[i],
+ GLX_BIND_TO_TEXTURE_TARGETS_EXT, &value);
+ if (!(value & GLX_TEXTURE_2D_BIT_EXT))
+ continue;
+
+ glXGetFBConfigAttrib(display, fbconfigs[i],
+ GLX_BIND_TO_TEXTURE_RGBA_EXT, &value);
+ if (value == False) {
+ glXGetFBConfigAttrib(display, fbconfigs[i],
+ GLX_BIND_TO_TEXTURE_RGB_EXT, &value);
+ if (value == False)
+ continue;
+ }
+
+ glXGetFBConfigAttrib(display, fbconfigs[i],
+ GLX_Y_INVERTED_EXT, &value);
+ if (value == True) {
+ top = 0.0f;
+ bottom = 1.0f;
+ }
+ else {
+ top = 1.0f;
+ bottom = 0.0f;
+ }
+
+ break;
+ }
+
+ if (i == nfbconfigs) {
+ printf("Unable to find FBconfig for texturing\n");
+ exit(1);
+ }
+
+ return fbconfigs[i];
+}
+
+
+static GLXPixmap
+CreatePixmap(Display *dpy, GLXFBConfig config, int w, int h, Pixmap *p)
+{
+ GLXPixmap gp;
+ const int pixmapAttribs[] = {
+ GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
+ GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT,
+ None
+ };
+ Window root = RootWindow(dpy, 0);
+
+ *p = XCreatePixmap(dpy, root, w, h, 24);
+ XSync(dpy, 0);
+ gp = glXCreatePixmap(dpy, config, *p, pixmapAttribs);
+ XSync(dpy, 0);
+
+ return gp;
+}
+
+
+static void
+DrawPixmapImage(Display *dpy, Pixmap pm, int w, int h)
+{
+ XGCValues gcvals;
+ GC gc;
+
+ gcvals.background = 0;
+ gc = XCreateGC(dpy, pm, GCBackground, &gcvals);
+
+ XSetForeground(dpy, gc, 0x0);
+ XFillRectangle(dpy, pm, gc, 0, 0, w, h);
+
+ XSetForeground(dpy, gc, 0xff0000);
+ XFillRectangle(dpy, pm, gc, 0, 0, 50, 50);
+
+ XSetForeground(dpy, gc, 0x00ff00);
+ XFillRectangle(dpy, pm, gc, w - 50, 0, 50, 50);
+
+ XSetForeground(dpy, gc, 0x0000ff);
+ XFillRectangle(dpy, pm, gc, 0, h - 50, 50, 50);
+
+ XSetForeground(dpy, gc, 0xffffff);
+ XFillRectangle(dpy, pm, gc, h - 50, h - 50, 50, 50);
+
+ XSetForeground(dpy, gc, 0xffff00);
+ XSetLineAttributes(dpy, gc, 3, LineSolid, CapButt, JoinBevel);
+ XDrawLine(dpy, pm, gc, 0, 0, w, h);
+ XDrawLine(dpy, pm, gc, 0, h, w, 0);
+
+ XFreeGC(dpy, gc);
+}
+
+
+static XVisualInfo *
+ChooseWindowVisual(Display *dpy)
+{
+ int screen = DefaultScreen(dpy);
+ XVisualInfo *visinfo;
+ int attribs[] = {
+ GLX_RGBA,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_DOUBLEBUFFER,
+ None
+ };
+
+ visinfo = glXChooseVisual(dpy, screen, attribs);
+ if (!visinfo) {
+ printf("Unable to find RGB, double-buffered visual\n");
+ exit(1);
+ }
+
+ return visinfo;
+}
+
+
+static Window
+CreateWindow(Display *dpy, XVisualInfo *visinfo,
+ int width, int height, const char *name)
+{
+ int screen = DefaultScreen(dpy);
+ Window win;
+ XSetWindowAttributes attr;
+ unsigned long mask;
+ Window root;
+
+ root = RootWindow(dpy, screen);
+
+ /* 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, 0, 0, width, height,
+ 0, visinfo->depth, InputOutput,
+ visinfo->visual, mask, &attr);
+ if (win) {
+ XSizeHints sizehints;
+ sizehints.width = width;
+ sizehints.height = height;
+ sizehints.flags = USSize;
+ XSetNormalHints(dpy, win, &sizehints);
+ XSetStandardProperties(dpy, win, name, name,
+ None, (char **)NULL, 0, &sizehints);
+
+ XMapWindow(dpy, win);
+ }
+ return win;
+}
+
+
+static void
+BindPixmapTexture(Display *dpy, GLXPixmap gp)
+{
+ GLuint texture;
+
+ glGenTextures(1, &texture);
+ glBindTexture(GL_TEXTURE_2D, texture);
+
+ glXBindTexImageEXT_func(dpy, gp, GLX_FRONT_LEFT_EXT, NULL);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ glEnable(GL_TEXTURE_2D);
+ /*
+ glXReleaseTexImageEXT_func(display, glxpixmap, GLX_FRONT_LEFT_EXT);
+ */
+}
+
+
+static void
+Resize(Window win, unsigned int width, unsigned int height)
+{
+ float sz = 1.5;
+ glViewport(0, 0, width, height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(-sz, sz, -sz, sz, -1.0, 1.0);
+ glMatrixMode(GL_MODELVIEW);
+}
+
+
+static void
+Redraw(Display *dpy, Window win, float rot)
+{
+ glClearColor(0.25, 0.25, 0.25, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glPushMatrix();
+ glRotatef(rot, 0, 0, 1);
+ glRotatef(2.0 * rot, 1, 0, 0);
+
+ glBegin(GL_QUADS);
+ glTexCoord2d(0.0, bottom);
+ glVertex2f(-1, -1);
+ glTexCoord2d(1.0, bottom);
+ glVertex2f( 1, -1);
+ glTexCoord2d(1.0, top);
+ glVertex2d(1.0, 1.0);
+ glTexCoord2d(0.0, top);
+ glVertex2f(-1.0, 1.0);
+ glEnd();
+
+ glPopMatrix();
+
+ glXSwapBuffers(dpy, win);
+}
+
+
+static void
+EventLoop(Display *dpy, Window win)
+{
+ GLfloat rot = 0.0;
+ int anim = 0;
+
+ while (1) {
+ if (!anim || XPending(dpy) > 0) {
+ XEvent event;
+ XNextEvent(dpy, &event);
+
+ switch (event.type) {
+ case Expose:
+ Redraw(dpy, win, rot);
+ break;
+ case ConfigureNotify:
+ Resize(event.xany.window,
+ event.xconfigure.width,
+ event.xconfigure.height);
+ break;
+ case KeyPress:
+ {
+ char buf[100];
+ KeySym keySym;
+ XComposeStatus stat;
+ XLookupString(&event.xkey, buf, sizeof(buf), &keySym, &stat);
+ if (keySym == XK_Escape) {
+ return; /* exit */
+ }
+ else if (keySym == XK_r) {
+ rot += 1.0;
+ Redraw(dpy, win, rot);
+ }
+ else if (keySym == XK_a) {
+ anim = !anim;
+ }
+ else if (keySym == XK_R) {
+ rot -= 1.0;
+ Redraw(dpy, win, rot);
+ }
+ }
+ break;
+ default:
+ ; /*no-op*/
+ }
+ }
+ else {
+ /* animate */
+ rot += 1.0;
+ Redraw(dpy, win, rot);
+ }
+ }
+}
+
+
+
+int
+main(int argc, char *argv[])
+{
+ Display *dpy;
+ GLXFBConfig pixmapConfig;
+ XVisualInfo *windowVis;
+ GLXPixmap gp;
+ Window win;
+ GLXContext ctx;
+ Pixmap p;
+
+ dpy = OpenDisplay();
+
+ pixmapConfig = ChoosePixmapFBConfig(dpy);
+ windowVis = ChooseWindowVisual(dpy);
+ win = CreateWindow(dpy, windowVis, 500, 500, "Texture From Pixmap");
+
+ gp = CreatePixmap(dpy, pixmapConfig, 512, 512, &p);
+ DrawPixmapImage(dpy, p, 512, 512);
+
+ ctx = glXCreateContext(dpy, windowVis, NULL, True);
+ if (!ctx) {
+ printf("Couldn't create GLX context\n");
+ exit(1);
+ }
+
+ glXMakeCurrent(dpy, win, ctx);
+
+ BindPixmapTexture(dpy, gp);
+
+ EventLoop(dpy, win);
+
+ return 0;
+}