132001f49Smrg/*
232001f49Smrg * Mesa 3-D graphics library
332001f49Smrg * Version:  6.5.2
432001f49Smrg *
532001f49Smrg * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
632001f49Smrg *
732001f49Smrg * Permission is hereby granted, free of charge, to any person obtaining a
832001f49Smrg * copy of this software and associated documentation files (the "Software"),
932001f49Smrg * to deal in the Software without restriction, including without limitation
1032001f49Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1132001f49Smrg * and/or sell copies of the Software, and to permit persons to whom the
1232001f49Smrg * Software is furnished to do so, subject to the following conditions:
1332001f49Smrg *
1432001f49Smrg * The above copyright notice and this permission notice shall be included
1532001f49Smrg * in all copies or substantial portions of the Software.
1632001f49Smrg *
1732001f49Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1832001f49Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1932001f49Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
2032001f49Smrg * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2132001f49Smrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2232001f49Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2332001f49Smrg */
2432001f49Smrg
2532001f49Smrg
2632001f49Smrg/*
2732001f49Smrg * This program opens two GLX windows, renders into one and uses
2832001f49Smrg * glCopyPixels to copy the image from the first window into the
2932001f49Smrg * second by means of the GLX 1.3 function glxMakeContextCurrent().
3032001f49Smrg * This function works just like the glXMakeCurrentReadSGI() function
3132001f49Smrg * in the GLX_SGI_make_current_read extension.
3232001f49Smrg */
3332001f49Smrg
3432001f49Smrg
3532001f49Smrg#define GL_GLEXT_PROTOTYPES
3632001f49Smrg#define GLX_GLXEXT_PROTOTYPES
3732001f49Smrg#include <GL/gl.h>
3832001f49Smrg#include <GL/glx.h>
3932001f49Smrg#include <X11/keysym.h>
4032001f49Smrg#include <stdio.h>
4132001f49Smrg#include <stdlib.h>
4232001f49Smrg#include <string.h>
4332001f49Smrg#include <unistd.h>
4432001f49Smrg
4532001f49Smrg
4632001f49Smrg#ifdef GLX_VERSION_1_3
4732001f49Smrg
4832001f49Smrg
4932001f49Smrgstatic Display *Dpy;
5032001f49Smrgstatic int ScrNum;
5132001f49Smrgstatic GLXContext Context;
5232001f49Smrgstatic Window Win[2];  /* Win[0] = source,  Win[1] = dest */
5332001f49Smrgstatic GLint Width[2], Height[2];
5432001f49Smrgstatic GLboolean TestClipping = GL_FALSE;
5532001f49Smrgstatic GLfloat Angle = 0.0;
5632001f49Smrg
5732001f49Smrgstatic GLboolean DrawFront = GL_FALSE;
5832001f49Smrg
5932001f49SmrgPFNGLXMAKECURRENTREADSGIPROC make_context_current = NULL;
6032001f49Smrg
6132001f49Smrgstatic Window
6232001f49SmrgCreateWindow(Display *dpy, int scrnum, XVisualInfo *visinfo,
6332001f49Smrg             int xpos, int ypos, int width, int height,
6432001f49Smrg             const char *name)
6532001f49Smrg{
6632001f49Smrg   Window win;
6732001f49Smrg   XSetWindowAttributes attr;
6832001f49Smrg   unsigned long mask;
6932001f49Smrg   Window root;
7032001f49Smrg
7132001f49Smrg   root = RootWindow(dpy, scrnum);
7232001f49Smrg
7332001f49Smrg   /* window attributes */
7432001f49Smrg   attr.background_pixel = 0;
7532001f49Smrg   attr.border_pixel = 0;
7632001f49Smrg   attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
7732001f49Smrg   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
7832001f49Smrg   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
7932001f49Smrg
8032001f49Smrg   win = XCreateWindow(dpy, root, xpos, ypos, width, height,
8132001f49Smrg		        0, visinfo->depth, InputOutput,
8232001f49Smrg		        visinfo->visual, mask, &attr);
8332001f49Smrg   if (win) {
8432001f49Smrg      XSizeHints sizehints;
8532001f49Smrg      sizehints.x = xpos;
8632001f49Smrg      sizehints.y = ypos;
8732001f49Smrg      sizehints.width  = width;
8832001f49Smrg      sizehints.height = height;
8932001f49Smrg      sizehints.flags = USSize | USPosition;
9032001f49Smrg      XSetNormalHints(dpy, win, &sizehints);
9132001f49Smrg      XSetStandardProperties(dpy, win, name, name,
9232001f49Smrg                              None, (char **)NULL, 0, &sizehints);
9332001f49Smrg
9432001f49Smrg      XMapWindow(dpy, win);
9532001f49Smrg   }
9632001f49Smrg   return win;
9732001f49Smrg}
9832001f49Smrg
9932001f49Smrg
10032001f49Smrgstatic void
10132001f49SmrgRedraw(void)
10232001f49Smrg{
10332001f49Smrg   /* make the first window the current one */
10432001f49Smrg   if (! (*make_context_current)(Dpy, Win[0], Win[0], Context)) {
10532001f49Smrg      printf("glXMakeContextCurrent failed in Redraw()\n");
10632001f49Smrg      return;
10732001f49Smrg   }
10832001f49Smrg
10932001f49Smrg   Angle += 1.0;
11032001f49Smrg
11132001f49Smrg   if (DrawFront) {
11232001f49Smrg      glDrawBuffer(GL_FRONT);
11332001f49Smrg      glReadBuffer(GL_FRONT);
11432001f49Smrg   }
11532001f49Smrg   else {
11632001f49Smrg      glDrawBuffer(GL_BACK);
11732001f49Smrg      glReadBuffer(GL_BACK);
11832001f49Smrg   }
11932001f49Smrg
12032001f49Smrg   glViewport(0, 0, Width[0], Height[0]);
12132001f49Smrg   glMatrixMode(GL_PROJECTION);
12232001f49Smrg   glLoadIdentity();
12332001f49Smrg   glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
12432001f49Smrg   glMatrixMode(GL_MODELVIEW);
12532001f49Smrg
12632001f49Smrg   glShadeModel(GL_FLAT);
12732001f49Smrg   glClearColor(0.5, 0.5, 0.5, 0.0);
12832001f49Smrg   glClear(GL_COLOR_BUFFER_BIT);
12932001f49Smrg
13032001f49Smrg   /* draw blue quad */
13132001f49Smrg   glColor3f(0.3, 0.3, 1.0);
13232001f49Smrg   glPushMatrix();
13332001f49Smrg   glRotatef(Angle, 0, 0, 1);
13432001f49Smrg   glBegin(GL_POLYGON);
13532001f49Smrg   glVertex2f(-0.5, -0.25);
13632001f49Smrg   glVertex2f( 0.5, -0.25);
13732001f49Smrg   glVertex2f( 0.5, 0.25);
13832001f49Smrg   glVertex2f(-0.5, 0.25);
13932001f49Smrg   glEnd();
14032001f49Smrg   glPopMatrix();
14132001f49Smrg
14232001f49Smrg   if (DrawFront)
14332001f49Smrg      glFinish();
14432001f49Smrg   else
14532001f49Smrg      glXSwapBuffers(Dpy, Win[0]);
14632001f49Smrg
14732001f49Smrg
14832001f49Smrg   /* copy image from window 0 to window 1 */
14932001f49Smrg   if (!(*make_context_current)(Dpy, Win[1], Win[0], Context)) {
15032001f49Smrg      printf("glXMakeContextCurrent failed in Redraw()\n");
15132001f49Smrg      return;
15232001f49Smrg   }
15332001f49Smrg
15432001f49Smrg   /* copy the image between windows */
15532001f49Smrg   glClearColor(0.0, 0.0, 0.0, 0.0);
15632001f49Smrg   glClear(GL_COLOR_BUFFER_BIT);
15732001f49Smrg
15832001f49Smrg   if (TestClipping) {
15932001f49Smrg      glWindowPos2iARB(-2, -2);
16032001f49Smrg      glCopyPixels(-2, -2, Width[0] + 4, Height[0] + 4, GL_COLOR);
16132001f49Smrg   }
16232001f49Smrg   else {
16332001f49Smrg      glWindowPos2iARB(0, 0);
16432001f49Smrg      glCopyPixels(0, 0, Width[0], Height[0], GL_COLOR);
16532001f49Smrg   }
16632001f49Smrg
16732001f49Smrg   if (DrawFront)
16832001f49Smrg      glFinish();
16932001f49Smrg   else
17032001f49Smrg      glXSwapBuffers(Dpy, Win[1]);
17132001f49Smrg}
17232001f49Smrg
17332001f49Smrg
17432001f49Smrg
17532001f49Smrgstatic void
17632001f49SmrgResize(Window win, unsigned int width, unsigned int height)
17732001f49Smrg{
17832001f49Smrg   int i;
17932001f49Smrg   if (win == Win[0]) {
18032001f49Smrg      i = 0;
18132001f49Smrg   }
18232001f49Smrg   else {
18332001f49Smrg      i = 1;
18432001f49Smrg   }
18532001f49Smrg   Width[i] = width;
18632001f49Smrg   Height[i] = height;
18732001f49Smrg   if (!glXMakeCurrent(Dpy, Win[i], Context)) {
18832001f49Smrg      printf("glXMakeCurrent failed in Resize()\n");
18932001f49Smrg      return;
19032001f49Smrg   }
19132001f49Smrg}
19232001f49Smrg
19332001f49Smrg
19432001f49Smrg
19532001f49Smrgstatic void
19632001f49SmrgEventLoop(void)
19732001f49Smrg{
19832001f49Smrg   XEvent event;
19932001f49Smrg   while (1) {
20032001f49Smrg      if (XPending(Dpy) > 0) {
20132001f49Smrg         XNextEvent( Dpy, &event );
20232001f49Smrg         switch (event.type) {
20332001f49Smrg            case Expose:
20432001f49Smrg               Redraw();
20532001f49Smrg               break;
20632001f49Smrg            case ConfigureNotify:
20732001f49Smrg               Resize(event.xany.window, event.xconfigure.width, event.xconfigure.height);
20832001f49Smrg               break;
20932001f49Smrg            case KeyPress:
21032001f49Smrg               {
21132001f49Smrg                  char buf[100];
21232001f49Smrg                  KeySym keySym;
21332001f49Smrg                  XComposeStatus stat;
21432001f49Smrg                  XLookupString(&event.xkey, buf, sizeof(buf), &keySym, &stat);
21532001f49Smrg                  if (keySym == XK_Escape) {
21632001f49Smrg                        /* exit */
21732001f49Smrg                        return;
21832001f49Smrg                  }
21932001f49Smrg                  else if (buf[0] == 'f') {
22032001f49Smrg                     DrawFront = !DrawFront;
22132001f49Smrg                     printf("Drawing to %s buffer\n",
22232001f49Smrg                            DrawFront ? "GL_FRONT" : "GL_BACK");
22332001f49Smrg                  }
22432001f49Smrg               }
22532001f49Smrg               break;
22632001f49Smrg            default:
22732001f49Smrg               /*no-op*/ ;
22832001f49Smrg         }
22932001f49Smrg      }
23032001f49Smrg      else {
23132001f49Smrg         /* animate */
23232001f49Smrg         Redraw();
23332001f49Smrg      }
23432001f49Smrg   }
23532001f49Smrg}
23632001f49Smrg
23732001f49Smrg
23832001f49Smrgstatic void
23932001f49SmrgInit(void)
24032001f49Smrg{
24132001f49Smrg   XVisualInfo *visinfo;
24232001f49Smrg   int attrib[] = { GLX_RGBA,
24332001f49Smrg		    GLX_RED_SIZE, 1,
24432001f49Smrg		    GLX_GREEN_SIZE, 1,
24532001f49Smrg		    GLX_BLUE_SIZE, 1,
24632001f49Smrg		    GLX_DOUBLEBUFFER,
24732001f49Smrg		    None };
24832001f49Smrg   int major, minor;
24932001f49Smrg
25032001f49Smrg   Dpy = XOpenDisplay(NULL);
25132001f49Smrg   if (!Dpy) {
25232001f49Smrg      printf("Couldn't open default display!\n");
25332001f49Smrg      exit(1);
25432001f49Smrg   }
25532001f49Smrg
25632001f49Smrg   ScrNum = DefaultScreen(Dpy);
25732001f49Smrg
25832001f49Smrg   glXQueryVersion(Dpy, &major, &minor);
25932001f49Smrg
26032001f49Smrg   if (major * 100 + minor >= 103) {
26132001f49Smrg      make_context_current = (PFNGLXMAKECURRENTREADSGIPROC)
26232001f49Smrg	  glXGetProcAddressARB( (GLubyte *) "glXMakeContextCurrent" );
26332001f49Smrg   }
26432001f49Smrg   else {
26532001f49Smrg      const char * const glxExtensions = glXQueryExtensionsString(Dpy, ScrNum);
26632001f49Smrg      const char * ext = strstr( glxExtensions, "GLX_SGI_make_current_read" );
26732001f49Smrg      const size_t len = strlen( "GLX_SGI_make_current_read" );
26832001f49Smrg
26932001f49Smrg      if ( (ext != NULL)
27032001f49Smrg	   && ((ext[len] == ' ') || (ext[len] == '\0')) ) {
27132001f49Smrg	 make_context_current = (PFNGLXMAKECURRENTREADSGIPROC)
27232001f49Smrg	     glXGetProcAddressARB( (GLubyte *) "glXMakeCurrentReadSGI" );
27332001f49Smrg      }
27432001f49Smrg   }
27532001f49Smrg
27632001f49Smrg   if (make_context_current == NULL) {
27732001f49Smrg      fprintf(stderr, "Sorry, this program requires either GLX 1.3 "
27832001f49Smrg	      "or GLX_SGI_make_current_read.\n");
27932001f49Smrg      exit(1);
28032001f49Smrg   }
28132001f49Smrg
28232001f49Smrg   visinfo = glXChooseVisual(Dpy, ScrNum, attrib);
28332001f49Smrg   if (!visinfo) {
28432001f49Smrg      printf("Unable to find RGB, double-buffered visual\n");
28532001f49Smrg      exit(1);
28632001f49Smrg   }
28732001f49Smrg
28832001f49Smrg   Context = glXCreateContext(Dpy, visinfo, NULL, True);
28932001f49Smrg   if (!Context) {
29032001f49Smrg      printf("Couldn't create GLX context\n");
29132001f49Smrg      exit(1);
29232001f49Smrg   }
29332001f49Smrg
29432001f49Smrg
29532001f49Smrg   Win[0] = CreateWindow(Dpy, ScrNum, visinfo,
29632001f49Smrg                         0, 0, 300, 300, "source window");
29732001f49Smrg
29832001f49Smrg   Win[1] = CreateWindow(Dpy, ScrNum, visinfo,
29932001f49Smrg                         350, 0, 300, 300, "dest window");
30032001f49Smrg
30132001f49Smrg   printf("Press Esc to exit\n");
30232001f49Smrg   printf("Press 'f' to toggle front/back buffer drawing\n");
30332001f49Smrg}
30432001f49Smrg
30532001f49Smrg
30632001f49Smrgint
30732001f49Smrgmain(int argc, char *argv[])
30832001f49Smrg{
30932001f49Smrg   if (argc > 1 && strcmp(argv[1], "-clip") == 0)
31032001f49Smrg      TestClipping = GL_TRUE;
31132001f49Smrg   Init();
31232001f49Smrg   EventLoop();
31332001f49Smrg   return 0;
31432001f49Smrg}
31532001f49Smrg
31632001f49Smrg
31732001f49Smrg#else
31832001f49Smrg
31932001f49Smrg
32032001f49Smrgint
32132001f49Smrgmain(int argc, char *argv[])
32232001f49Smrg{
32332001f49Smrg   printf("This program requires GLX 1.3!\n");
32432001f49Smrg   return 0;
32532001f49Smrg}
32632001f49Smrg
32732001f49Smrg
32832001f49Smrg#endif /* GLX_VERSION_1_3 */
329