Ian Romanick wrote:
To test things, I've been using a modified version of our favorite glxgears (patch attached) that uses two windows.

Eh-hem. The summer heat must have melted my brain. The patch is actually attached this time. :)
Index: glxgears.c
===================================================================
RCS file: /cvsroot/mesa3d/Mesa/xdemos/glxgears.c,v
retrieving revision 1.7
diff -u -d -r1.7 glxgears.c
--- glxgears.c  30 May 2003 18:41:38 -0000      1.7
+++ glxgears.c  2 Jul 2003 16:26:42 -0000
@@ -48,6 +48,8 @@
 #include <GL/gl.h>
 #include <GL/glx.h>
 
+#include <assert.h>
+
 #ifndef GLX_MESA_swap_control
 typedef GLint ( * PFNGLXSWAPINTERVALMESAPROC) (unsigned interval);
 typedef GLint ( * PFNGLXGETSWAPINTERVALMESAPROC) ( void );
@@ -112,7 +114,9 @@
 static GLint gear1, gear2, gear3;
 static GLfloat angle = 0.0;
 
+static GLboolean has_GLX_1_3 = GL_FALSE;
 static GLboolean has_OML_sync_control = GL_FALSE;
+static GLboolean has_SGI_make_current_read = GL_FALSE;
 static GLboolean has_SGI_swap_control = GL_FALSE;
 static GLboolean has_MESA_swap_control = GL_FALSE;
 static GLboolean has_MESA_swap_frame_usage = GL_FALSE;
@@ -266,6 +270,7 @@
 draw(void)
 {
    if ( use_ztrick ) {
+      unsigned   i;
       static GLboolean flip = GL_FALSE;
       static const GLfloat vert[4][3] = {
         { -1, -1, -0.999 },
@@ -352,9 +357,74 @@
 }
 
 
+static void
+draw2( Display * dpy, Window * win, GLXContext ctx )
+{
+   GLboolean   result;
+
+   if ( has_GLX_1_3 ) {
+      result = glXMakeContextCurrent(dpy, win[1], win[0], ctx);
+   }
+   else if ( has_SGI_make_current_read ) {
+      result = glXMakeCurrentReadSGI(dpy, win[1], win[0], ctx);
+   }
+   else {
+      result = glXMakeCurrent(dpy, win[0], ctx);
+   }
+
+   /* FIXME: If this fails, how can the app determine why it failed? */
+   assert( result );
+
+   glBindTexture( GL_TEXTURE_2D, 1 );
+   glCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, 300, 300 );
+
+   if ( ! (has_GLX_1_3 || has_SGI_make_current_read) ) {
+      result = glXMakeCurrent(dpy, win[1], ctx);
+      assert( result );
+   }
+
+   glBindTexture( GL_TEXTURE_2D, 1 );
+
+   glDisable(GL_CULL_FACE);
+   glDisable(GL_LIGHTING);
+   glDisable(GL_LIGHT0);
+   glDisable(GL_DEPTH_TEST);
+   glEnable(GL_TEXTURE_2D);
+
+   glMatrixMode(GL_TEXTURE);
+   glLoadIdentity();
+   glTranslatef(0.5, 0.5, 0.0);
+   glRotatef(angle, 0, 0, 1);
+   glTranslatef(-0.5, -0.5, 0.0);
+   glMatrixMode(GL_MODELVIEW);
+
+   glBegin(GL_POLYGON);
+
+   glTexCoord2f( 0.0, 0.0 );
+   glVertex2f( -5.0, -5.0 );
+
+   glTexCoord2f( 0.0, 0.0 );
+   glVertex2f( 5.0, -5.0 );
+
+   glTexCoord2f( 1.0, 1.0 );
+   glVertex2f( 5.0, 5.0 );
+
+   glTexCoord2f( 0.0, 1.0 );
+   glVertex2f( -5.0, 5.0 );
+
+   glEnd();
+
+   glDisable(GL_TEXTURE_2D);
+   glEnable(GL_CULL_FACE);
+   glEnable(GL_LIGHTING);
+   glEnable(GL_LIGHT0);
+   glEnable(GL_DEPTH_TEST);
+}
+
+
 /* new window size or exposure */
 static void
-reshape(int width, int height)
+reshape(Window win, int width, int height)
 {
    aspect = (GLfloat) height / (GLfloat) width;
 
@@ -371,7 +441,7 @@
 
 
 static void
-init(void)
+init(GLboolean create_texture_object)
 {
    static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 };
    static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
@@ -404,6 +474,21 @@
    glEndList();
 
    glEnable(GL_NORMALIZE);
+   
+
+   /* Initialize the texture object so that glCopyTexSubImage2D can be used
+    * to update its contents.
+    */
+
+   if ( create_texture_object ) {
+      glBindTexture(GL_TEXTURE_2D, 1);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 512, 512, 0, GL_RGB, GL_BYTE,
+                  NULL);
+   }
 }
 
 
@@ -414,7 +499,8 @@
 static void
 make_window( Display *dpy, const char *name,
              int x, int y, int width, int height,
-             Window *winRet, GLXContext *ctxRet)
+             Window *winRet, GLXContext *ctxRet,
+            GLboolean two_windows )
 {
    int attrib[] = { GLX_RGBA,
                    GLX_RED_SIZE, 1,
@@ -427,9 +513,8 @@
    XSetWindowAttributes attr;
    unsigned long mask;
    Window root;
-   Window win;
-   GLXContext ctx;
    XVisualInfo *visinfo;
+   XSizeHints sizehints;
 
    scrnum = DefaultScreen( dpy );
    root = RootWindow( dpy, scrnum );
@@ -447,51 +532,72 @@
    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 );
+   winRet[0] = XCreateWindow( dpy, root, 0, 0, width, height,
+                             0, visinfo->depth, InputOutput,
+                             visinfo->visual, mask, &attr );
 
    /* set hints and properties */
-   {
-      XSizeHints sizehints;
-      sizehints.x = x;
+   sizehints.x = x;
+   sizehints.y = y;
+   sizehints.width  = width;
+   sizehints.height = height;
+   sizehints.flags = USSize | USPosition;
+   XSetNormalHints(dpy, winRet[0], &sizehints);
+   XSetStandardProperties(dpy, winRet[0], name, name,
+                         None, (char **)NULL, 0, &sizehints);
+
+   if ( two_windows ) {
+         /* 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;
+
+      winRet[1] = XCreateWindow( dpy, root, 0, 0, width, height,
+                                0, visinfo->depth, InputOutput,
+                                visinfo->visual, mask, &attr );
+
+      /* set hints and properties */
+      sizehints.x = x + width + 10;
       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);
+      XSetNormalHints(dpy, winRet[1], &sizehints);
+      XSetStandardProperties(dpy, winRet[1], "second window", "2nd win",
+                            None, (char **)NULL, 0, &sizehints);
+   }
+   else {
+      winRet[1] = None;
    }
 
-   ctx = glXCreateContext( dpy, visinfo, NULL, True );
-   if (!ctx) {
+   ctxRet[0] = glXCreateContext( dpy, visinfo, NULL, True );
+   if (! ctxRet[0] ) {
       printf("Error: glXCreateContext failed\n");
       exit(1);
    }
 
    XFree(visinfo);
-
-   *winRet = win;
-   *ctxRet = ctx;
 }
 
 
 static void
-event_loop(Display *dpy, Window win)
+event_loop(Display *dpy, Window *win, GLXContext ctx)
 {
    float  frame_usage = 0.0;
 
    while (1) {
       while (XPending(dpy) > 0) {
-         XEvent event;
-         XNextEvent(dpy, &event);
+        XEvent event;
+        XNextEvent(dpy, &event);
          switch (event.type) {
         case Expose:
             /* we'll redraw below */
            break;
         case ConfigureNotify:
-           reshape(event.xconfigure.width, event.xconfigure.height);
+           reshape(event.xany.window, 
+                   event.xconfigure.width, event.xconfigure.height);
            break;
          case KeyPress:
             {
@@ -525,15 +631,21 @@
       /* next frame */
       angle += 2.0;
 
+      glXMakeCurrent(dpy, win[0], ctx);
       draw();
       if ( get_frame_usage != NULL ) {
         GLfloat   temp;
         
-        (*get_frame_usage)( dpy, win, & temp );
+        (*get_frame_usage)( dpy, win[0], & temp );
         frame_usage += temp;
       }
 
-      glXSwapBuffers(dpy, win);
+      if ( win[1] != None ) {
+        draw2( dpy, win, ctx );
+        glXSwapBuffers(dpy, win[1]);
+      }
+
+      glXSwapBuffers(dpy, win[0]);
 
       /* calc framerate */
       {
@@ -699,16 +811,19 @@
 main(int argc, char *argv[])
 {
    Display *dpy;
-   Window win;
+   Window win[2];
    GLXContext ctx;
    char *dpyName = ":0";
    int swap_interval = 1;
    GLboolean do_swap_interval = GL_FALSE;
    GLboolean force_get_rate = GL_FALSE;
    GLboolean printInfo = GL_FALSE;
+   GLboolean use_two_windows = GL_FALSE;
    int i;
    PFNGLXSWAPINTERVALMESAPROC set_swap_interval = NULL;
    PFNGLXGETSWAPINTERVALMESAPROC get_swap_interval = NULL;
+   GLint major;
+   GLint minor;
 
 
    for (i = 1; i < argc; i++) {
@@ -734,6 +849,9 @@
       else if (strcmp(argv[i], "-ztrick") == 0) {
         use_ztrick = GL_TRUE;
       }
+      else if (strcmp(argv[i], "-twowindow") == 0) {
+        use_two_windows = GL_TRUE;
+      }
       else if (strcmp(argv[i], "-help") == 0) {
          printf("Usage:\n");
          printf("  gears [options]\n");
@@ -743,6 +861,12 @@
          printf("  -info                   Display GL information\n");
          printf("  -swap N                 Swap no more than once per N vertical 
refreshes\n");
          printf("  -forcegetrate           Try to use glXGetMscRateOML function\n");
+        printf("  -ztrick                 Use the Quake 2 / Half-Life style 
\"Z-trick\" to\n"
+               "                          avoid calling glClear.  For testing only.  
Does not\n"
+               "                          speed-up gears!\n" );
+        printf("  -twowindow              Use two windows to test using one window as 
a texture\n"
+               "                          for the other window.  Tests GLX 1.3 and / 
or\n"
+               "                          SGI_make_current_read.\n" );
          return 0;
       }
    }
@@ -753,16 +877,19 @@
       return -1;
    }
 
-   make_window(dpy, "glxgears", 0, 0, 300, 300, &win, &ctx);
-   XMapWindow(dpy, win);
-   glXMakeCurrent(dpy, win, ctx);
+   make_window(dpy, "glxgears", 0, 0, 300, 300, win, &ctx, use_two_windows);
+   glXMakeCurrent( dpy, win[0], ctx );
 
    make_extension_table( (char *) glXQueryExtensionsString(dpy,DefaultScreen(dpy)) );
    has_OML_sync_control = is_extension_supported( "GLX_OML_sync_control" );
+   has_SGI_make_current_read = is_extension_supported( "GLX_SGI_make_current_read" );
    has_SGI_swap_control = is_extension_supported( "GLX_SGI_swap_control" );
    has_MESA_swap_control = is_extension_supported( "GLX_MESA_swap_control" );
    has_MESA_swap_frame_usage = is_extension_supported( "GLX_MESA_swap_frame_usage" );
 
+   glXQueryVersion( dpy, & major, & minor );
+   has_GLX_1_3 = (major > 1) || ((major == 1) && (minor >= 3));
+
    if ( has_MESA_swap_control ) {
       set_swap_interval = (PFNGLXSWAPINTERVALMESAPROC) glXGetProcAddressARB( (const 
GLubyte *) "glXSwapIntervalMESA" );
       get_swap_interval = (PFNGLXGETSWAPINTERVALMESAPROC) glXGetProcAddressARB( 
(const GLubyte *) "glXGetSwapIntervalMESA" );
@@ -786,6 +913,16 @@
         show_refresh_rate( dpy );
       }
 
+      if ( has_GLX_1_3 ) {
+        printf( "Using glXMakeContextCurrent.\n" );
+      }
+      else if ( has_SGI_make_current_read ) {
+        printf( "Using glXMakeCurrentReadSGI.\n" );
+      }
+      else {
+        printf( "Using glXMakeCurrent.\n" );
+      }
+
       if ( get_swap_interval != NULL ) {
         printf("Default swap interval = %d\n", (*get_swap_interval)() );
       }
@@ -812,12 +949,21 @@
       }
    }
 
-   init();
+   if ( win[1] != None ) {
+      XMapWindow(dpy, win[1]);
+   }
 
-   event_loop(dpy, win);
+   XMapWindow(dpy, win[0]);
+   glXMakeCurrent(dpy, win[0], ctx);
+   init( use_two_windows );
+
+   event_loop(dpy, win, ctx);
 
    glXDestroyContext(dpy, ctx);
-   XDestroyWindow(dpy, win);
+   XDestroyWindow(dpy, win[0]);
+   if ( win[1] != None ) {
+      XDestroyWindow(dpy, win[1]);
+   }
    XCloseDisplay(dpy);
 
    return 0;

Reply via email to