132001f49Smrg
232001f49Smrg/*
332001f49Smrg * Test sharing of display lists and texture objects between GLX contests.
432001f49Smrg * Brian Paul
532001f49Smrg * Summer 2000
632001f49Smrg *
732001f49Smrg *
832001f49Smrg * Copyright (C) 2000  Brian Paul   All Rights Reserved.
932001f49Smrg *
1032001f49Smrg * Permission is hereby granted, free of charge, to any person obtaining a
1132001f49Smrg * copy of this software and associated documentation files (the "Software"),
1232001f49Smrg * to deal in the Software without restriction, including without limitation
1332001f49Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1432001f49Smrg * and/or sell copies of the Software, and to permit persons to whom the
1532001f49Smrg * Software is furnished to do so, subject to the following conditions:
1632001f49Smrg *
1732001f49Smrg * The above copyright notice and this permission notice shall be included
1832001f49Smrg * in all copies or substantial portions of the Software.
1932001f49Smrg *
2032001f49Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
2132001f49Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2232001f49Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
2332001f49Smrg * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2432001f49Smrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2532001f49Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2632001f49Smrg */
2732001f49Smrg
2832001f49Smrg
2932001f49Smrg#include <GL/gl.h>
3032001f49Smrg#include <GL/glx.h>
3132001f49Smrg#include <stdio.h>
3232001f49Smrg#include <stdlib.h>
3332001f49Smrg#include <unistd.h>
3432001f49Smrg#include <string.h>
3532001f49Smrg
3632001f49Smrg
3732001f49Smrgstruct window {
3832001f49Smrg   char DisplayName[1000];
3932001f49Smrg   Display *Dpy;
4032001f49Smrg   Window Win;
4132001f49Smrg   GLXContext Context;
4232001f49Smrg   float Angle;
4332001f49Smrg   int Id;
4432001f49Smrg};
4532001f49Smrg
4632001f49Smrg
4732001f49Smrg#define MAX_WINDOWS 20
4832001f49Smrgstatic struct window Windows[MAX_WINDOWS];
4932001f49Smrgstatic int NumWindows = 0;
5032001f49Smrg
5132001f49Smrg
5232001f49Smrgstatic GLuint Textures[3];
5332001f49Smrgstatic GLuint CubeList;
5432001f49Smrg
5532001f49Smrg
5632001f49Smrg
5732001f49Smrgstatic void
5832001f49SmrgError(const char *display, const char *msg)
5932001f49Smrg{
6032001f49Smrg   fprintf(stderr, "Error on display %s - %s\n", display, msg);
6132001f49Smrg   exit(1);
6232001f49Smrg}
6332001f49Smrg
6432001f49Smrg
6532001f49Smrgstatic struct window *
6632001f49SmrgAddWindow(const char *displayName, int xpos, int ypos,
6732001f49Smrg          const struct window *shareWindow)
6832001f49Smrg{
6932001f49Smrg   Display *dpy;
7032001f49Smrg   Window win;
7132001f49Smrg   GLXContext ctx;
7232001f49Smrg   int attrib[] = { GLX_RGBA,
7332001f49Smrg		    GLX_RED_SIZE, 1,
7432001f49Smrg		    GLX_GREEN_SIZE, 1,
7532001f49Smrg		    GLX_BLUE_SIZE, 1,
7632001f49Smrg		    GLX_DOUBLEBUFFER,
7732001f49Smrg                    GLX_DEPTH_SIZE, 1,
7832001f49Smrg		    None };
7932001f49Smrg   int scrnum;
8032001f49Smrg   XSetWindowAttributes attr;
8132001f49Smrg   unsigned long mask;
8232001f49Smrg   Window root;
8332001f49Smrg   XVisualInfo *visinfo;
8432001f49Smrg   int width = 300, height = 300;
8532001f49Smrg
8632001f49Smrg   if (NumWindows >= MAX_WINDOWS)
8732001f49Smrg      return NULL;
8832001f49Smrg
8932001f49Smrg   dpy = XOpenDisplay(displayName);
9032001f49Smrg   if (!dpy) {
9132001f49Smrg      Error(displayName, "Unable to open display");
9232001f49Smrg      return NULL;
9332001f49Smrg   }
9432001f49Smrg
9532001f49Smrg   scrnum = DefaultScreen(dpy);
9632001f49Smrg   root = RootWindow(dpy, scrnum);
9732001f49Smrg
9832001f49Smrg   visinfo = glXChooseVisual(dpy, scrnum, attrib);
9932001f49Smrg   if (!visinfo) {
10032001f49Smrg      Error(displayName, "Unable to find RGB, double-buffered visual");
10132001f49Smrg      return NULL;
10232001f49Smrg   }
10332001f49Smrg
10432001f49Smrg   /* window attributes */
10532001f49Smrg   attr.background_pixel = 0;
10632001f49Smrg   attr.border_pixel = 0;
10732001f49Smrg   attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
10832001f49Smrg   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
10932001f49Smrg   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
11032001f49Smrg
11132001f49Smrg   win = XCreateWindow(dpy, root, xpos, ypos, width, height,
11232001f49Smrg		        0, visinfo->depth, InputOutput,
11332001f49Smrg		        visinfo->visual, mask, &attr);
11432001f49Smrg   if (!win) {
11532001f49Smrg      Error(displayName, "Couldn't create window");
11632001f49Smrg      return NULL;
11732001f49Smrg   }
11832001f49Smrg
11932001f49Smrg   {
12032001f49Smrg      XSizeHints sizehints;
12132001f49Smrg      sizehints.x = xpos;
12232001f49Smrg      sizehints.y = ypos;
12332001f49Smrg      sizehints.width  = width;
12432001f49Smrg      sizehints.height = height;
12532001f49Smrg      sizehints.flags = USSize | USPosition;
12632001f49Smrg      XSetNormalHints(dpy, win, &sizehints);
12732001f49Smrg      XSetStandardProperties(dpy, win, displayName, displayName,
12832001f49Smrg                              None, (char **)NULL, 0, &sizehints);
12932001f49Smrg   }
13032001f49Smrg
13132001f49Smrg
13232001f49Smrg   ctx = glXCreateContext(dpy, visinfo,
13332001f49Smrg                          shareWindow ? shareWindow->Context : NULL,
13432001f49Smrg                          True);
13532001f49Smrg   if (!ctx) {
13632001f49Smrg      Error(displayName, "Couldn't create GLX context");
13732001f49Smrg      return NULL;
13832001f49Smrg   }
13932001f49Smrg
14032001f49Smrg   XMapWindow(dpy, win);
14132001f49Smrg
14232001f49Smrg   if (!glXMakeCurrent(dpy, win, ctx)) {
14332001f49Smrg      Error(displayName, "glXMakeCurrent failed");
14432001f49Smrg      printf("glXMakeCurrent failed in Redraw()\n");
14532001f49Smrg      return NULL;
14632001f49Smrg   }
14732001f49Smrg
14832001f49Smrg   /* save the info for this window */
14932001f49Smrg   {
15032001f49Smrg      static int id = 0;
15132001f49Smrg      struct window *h = &Windows[NumWindows];
15232001f49Smrg      strcpy(h->DisplayName, displayName);
15332001f49Smrg      h->Dpy = dpy;
15432001f49Smrg      h->Win = win;
15532001f49Smrg      h->Context = ctx;
15632001f49Smrg      h->Angle = 0.0;
15732001f49Smrg      h->Id = id++;
15832001f49Smrg      NumWindows++;
15932001f49Smrg      return &Windows[NumWindows-1];
16032001f49Smrg   }
16132001f49Smrg
16232001f49Smrg}
16332001f49Smrg
16432001f49Smrg
16532001f49Smrgstatic void
16632001f49SmrgInitGLstuff(struct window *h)
16732001f49Smrg{
16832001f49Smrg   if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) {
16932001f49Smrg      Error(h->DisplayName, "glXMakeCurrent failed in InitGLstuff");
17032001f49Smrg      return;
17132001f49Smrg   }
17232001f49Smrg
17332001f49Smrg   glGenTextures(3, Textures);
17432001f49Smrg
17532001f49Smrg   /* setup first texture object */
17632001f49Smrg   {
17732001f49Smrg      GLubyte image[16][16][4];
17832001f49Smrg      GLint i, j;
17932001f49Smrg      glBindTexture(GL_TEXTURE_2D, Textures[0]);
18032001f49Smrg
18132001f49Smrg      /* red/white checkerboard */
18232001f49Smrg      for (i = 0; i < 16; i++) {
18332001f49Smrg         for (j = 0; j < 16; j++) {
18432001f49Smrg            if ((i ^ j) & 1) {
18532001f49Smrg               image[i][j][0] = 255;
18632001f49Smrg               image[i][j][1] = 255;
18732001f49Smrg               image[i][j][2] = 255;
18832001f49Smrg               image[i][j][3] = 255;
18932001f49Smrg            }
19032001f49Smrg            else {
19132001f49Smrg               image[i][j][0] = 255;
19232001f49Smrg               image[i][j][1] = 0;
19332001f49Smrg               image[i][j][2] = 0;
19432001f49Smrg               image[i][j][3] = 255;
19532001f49Smrg            }
19632001f49Smrg         }
19732001f49Smrg      }
19832001f49Smrg
19932001f49Smrg      glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
20032001f49Smrg      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
20132001f49Smrg                   GL_UNSIGNED_BYTE, image);
20232001f49Smrg      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
20332001f49Smrg      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
20432001f49Smrg   }
20532001f49Smrg
20632001f49Smrg   /* setup second texture object */
20732001f49Smrg   {
20832001f49Smrg      GLubyte image[8][8][3];
20932001f49Smrg      GLint i, j;
21032001f49Smrg      glBindTexture(GL_TEXTURE_2D, Textures[1]);
21132001f49Smrg
21232001f49Smrg      /* green/yellow checkerboard */
21332001f49Smrg      for (i = 0; i < 8; i++) {
21432001f49Smrg         for (j = 0; j < 8; j++) {
21532001f49Smrg            if ((i ^ j) & 1) {
21632001f49Smrg               image[i][j][0] = 0;
21732001f49Smrg               image[i][j][1] = 255;
21832001f49Smrg               image[i][j][2] = 0;
21932001f49Smrg            }
22032001f49Smrg            else {
22132001f49Smrg               image[i][j][0] = 255;
22232001f49Smrg               image[i][j][1] = 255;
22332001f49Smrg               image[i][j][2] = 0;
22432001f49Smrg            }
22532001f49Smrg         }
22632001f49Smrg      }
22732001f49Smrg
22832001f49Smrg      glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
22932001f49Smrg      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB,
23032001f49Smrg                   GL_UNSIGNED_BYTE, image);
23132001f49Smrg      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
23232001f49Smrg      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
23332001f49Smrg   }
23432001f49Smrg
23532001f49Smrg   /* setup second texture object */
23632001f49Smrg   {
23732001f49Smrg      GLubyte image[4][4][3];
23832001f49Smrg      GLint i, j;
23932001f49Smrg      glBindTexture(GL_TEXTURE_2D, Textures[2]);
24032001f49Smrg
24132001f49Smrg      /* blue/gray checkerboard */
24232001f49Smrg      for (i = 0; i < 4; i++) {
24332001f49Smrg         for (j = 0; j < 4; j++) {
24432001f49Smrg            if ((i ^ j) & 1) {
24532001f49Smrg               image[i][j][0] = 0;
24632001f49Smrg               image[i][j][1] = 0;
24732001f49Smrg               image[i][j][2] = 255;
24832001f49Smrg            }
24932001f49Smrg            else {
25032001f49Smrg               image[i][j][0] = 200;
25132001f49Smrg               image[i][j][1] = 200;
25232001f49Smrg               image[i][j][2] = 200;
25332001f49Smrg            }
25432001f49Smrg         }
25532001f49Smrg      }
25632001f49Smrg
25732001f49Smrg      glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
25832001f49Smrg      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 4, 4, 0, GL_RGB,
25932001f49Smrg                   GL_UNSIGNED_BYTE, image);
26032001f49Smrg      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
26132001f49Smrg      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
26232001f49Smrg   }
26332001f49Smrg
26432001f49Smrg   /* Now make the cube object display list */
26532001f49Smrg   CubeList = glGenLists(1);
26632001f49Smrg   glNewList(CubeList, GL_COMPILE);
26732001f49Smrg   {
26832001f49Smrg      glBindTexture(GL_TEXTURE_2D, Textures[0]);
26932001f49Smrg      glBegin(GL_POLYGON);
27032001f49Smrg      glTexCoord2f(0, 0);  glVertex3f(-1, -1, -1);
27132001f49Smrg      glTexCoord2f(1, 0);  glVertex3f(-1,  1, -1);
27232001f49Smrg      glTexCoord2f(1, 1);  glVertex3f(-1,  1,  1);
27332001f49Smrg      glTexCoord2f(0, 1);  glVertex3f(-1, -1,  1);
27432001f49Smrg      glEnd();
27532001f49Smrg      glBegin(GL_POLYGON);
27632001f49Smrg      glTexCoord2f(0, 0);  glVertex3f(1, -1, -1);
27732001f49Smrg      glTexCoord2f(1, 0);  glVertex3f(1,  1, -1);
27832001f49Smrg      glTexCoord2f(1, 1);  glVertex3f(1,  1,  1);
27932001f49Smrg      glTexCoord2f(0, 1);  glVertex3f(1, -1,  1);
28032001f49Smrg      glEnd();
28132001f49Smrg
28232001f49Smrg      glBindTexture(GL_TEXTURE_2D, Textures[1]);
28332001f49Smrg      glBegin(GL_POLYGON);
28432001f49Smrg      glTexCoord2f(0, 0);  glVertex3f(-1, -1, -1);
28532001f49Smrg      glTexCoord2f(1, 0);  glVertex3f( 1, -1, -1);
28632001f49Smrg      glTexCoord2f(1, 1);  glVertex3f( 1, -1,  1);
28732001f49Smrg      glTexCoord2f(0, 1);  glVertex3f(-1, -1,  1);
28832001f49Smrg      glEnd();
28932001f49Smrg      glBegin(GL_POLYGON);
29032001f49Smrg      glTexCoord2f(0, 0);  glVertex3f(-1, 1, -1);
29132001f49Smrg      glTexCoord2f(1, 0);  glVertex3f( 1, 1, -1);
29232001f49Smrg      glTexCoord2f(1, 1);  glVertex3f( 1, 1,  1);
29332001f49Smrg      glTexCoord2f(0, 1);  glVertex3f(-1, 1,  1);
29432001f49Smrg      glEnd();
29532001f49Smrg
29632001f49Smrg      glBindTexture(GL_TEXTURE_2D, Textures[2]);
29732001f49Smrg      glBegin(GL_POLYGON);
29832001f49Smrg      glTexCoord2f(0, 0);  glVertex3f(-1, -1, -1);
29932001f49Smrg      glTexCoord2f(1, 0);  glVertex3f( 1, -1, -1);
30032001f49Smrg      glTexCoord2f(1, 1);  glVertex3f( 1,  1, -1);
30132001f49Smrg      glTexCoord2f(0, 1);  glVertex3f(-1,  1, -1);
30232001f49Smrg      glEnd();
30332001f49Smrg      glBegin(GL_POLYGON);
30432001f49Smrg      glTexCoord2f(0, 0);  glVertex3f(-1, -1, 1);
30532001f49Smrg      glTexCoord2f(1, 0);  glVertex3f( 1, -1, 1);
30632001f49Smrg      glTexCoord2f(1, 1);  glVertex3f( 1,  1, 1);
30732001f49Smrg      glTexCoord2f(0, 1);  glVertex3f(-1,  1, 1);
30832001f49Smrg      glEnd();
30932001f49Smrg   }
31032001f49Smrg   glEndList();
31132001f49Smrg
31232001f49Smrg   printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER));
31332001f49Smrg   printf("GL_VERSION: %s\n", (char *) glGetString(GL_VERSION));
31432001f49Smrg   printf("GL_VENDOR: %s\n", (char *) glGetString(GL_VENDOR));
31532001f49Smrg}
31632001f49Smrg
31732001f49Smrg
31832001f49Smrg
31932001f49Smrgstatic void
32032001f49SmrgRedraw(struct window *h)
32132001f49Smrg{
32232001f49Smrg   if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) {
32332001f49Smrg      Error(h->DisplayName, "glXMakeCurrent failed");
32432001f49Smrg      printf("glXMakeCurrent failed in Redraw()\n");
32532001f49Smrg      return;
32632001f49Smrg   }
32732001f49Smrg
32832001f49Smrg   h->Angle += 1.0;
32932001f49Smrg
33032001f49Smrg   glShadeModel(GL_FLAT);
33132001f49Smrg   glClearColor(0.25, 0.25, 0.25, 1.0);
33232001f49Smrg   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
33332001f49Smrg
33432001f49Smrg   glEnable(GL_TEXTURE_2D);
33532001f49Smrg   glEnable(GL_DEPTH_TEST);
33632001f49Smrg   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
33732001f49Smrg
33832001f49Smrg   glColor3f(1, 1, 1);
33932001f49Smrg
34032001f49Smrg   glPushMatrix();
34132001f49Smrg      if (h->Id == 0)
34232001f49Smrg         glRotatef(h->Angle, 0, 1, -1);
34332001f49Smrg      else if (h->Id == 1)
34432001f49Smrg         glRotatef(-(h->Angle), 0, 1, -1);
34532001f49Smrg      else if (h->Id == 2)
34632001f49Smrg         glRotatef(h->Angle, 0, 1, 1);
34732001f49Smrg      else if (h->Id == 3)
34832001f49Smrg         glRotatef(-(h->Angle), 0, 1, 1);
34932001f49Smrg      glCallList(CubeList);
35032001f49Smrg   glPopMatrix();
35132001f49Smrg
35232001f49Smrg   glXSwapBuffers(h->Dpy, h->Win);
35332001f49Smrg}
35432001f49Smrg
35532001f49Smrg
35632001f49Smrg
35732001f49Smrgstatic void
35832001f49SmrgResize(const struct window *h, unsigned int width, unsigned int height)
35932001f49Smrg{
36032001f49Smrg   if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) {
36132001f49Smrg      Error(h->DisplayName, "glXMakeCurrent failed in Resize()");
36232001f49Smrg      return;
36332001f49Smrg   }
36432001f49Smrg   glViewport(0, 0, width, height);
36532001f49Smrg   glMatrixMode(GL_PROJECTION);
36632001f49Smrg   glLoadIdentity();
36732001f49Smrg   glFrustum(-1, 1, -1, 1, 2, 10);
36832001f49Smrg   glMatrixMode(GL_MODELVIEW);
36932001f49Smrg   glLoadIdentity();
37032001f49Smrg   glTranslatef(0, 0, -4.5);
37132001f49Smrg}
37232001f49Smrg
37332001f49Smrg
37432001f49Smrg
37532001f49Smrgstatic void
37632001f49SmrgEventLoop(void)
37732001f49Smrg{
37832001f49Smrg   while (1) {
37932001f49Smrg      int i;
38032001f49Smrg      for (i = 0; i < NumWindows; i++) {
38132001f49Smrg         struct window *h = &Windows[i];
38232001f49Smrg         while (XPending(h->Dpy) > 0) {
38332001f49Smrg            XEvent event;
38432001f49Smrg            XNextEvent(h->Dpy, &event);
38532001f49Smrg            if (event.xany.window == h->Win) {
38632001f49Smrg               switch (event.type) {
38732001f49Smrg                  case Expose:
38832001f49Smrg                     Redraw(h);
38932001f49Smrg                     break;
39032001f49Smrg                  case ConfigureNotify:
39132001f49Smrg                     Resize(h, event.xconfigure.width, event.xconfigure.height);
39232001f49Smrg                     break;
39332001f49Smrg                  case KeyPress:
39432001f49Smrg                     return;
39532001f49Smrg                  default:
39632001f49Smrg                     /*no-op*/ ;
39732001f49Smrg               }
39832001f49Smrg            }
39932001f49Smrg            else {
40032001f49Smrg               printf("window mismatch\n");
40132001f49Smrg            }
40232001f49Smrg         }
40332001f49Smrg         Redraw(h);
40432001f49Smrg      }
40532001f49Smrg      usleep(1);
40632001f49Smrg   }
40732001f49Smrg}
40832001f49Smrg
40932001f49Smrg
41032001f49Smrg#if 0
41132001f49Smrgstatic void
41232001f49SmrgPrintInfo(const struct window *h)
41332001f49Smrg{
41432001f49Smrg   printf("Name: %s\n", h->DisplayName);
41532001f49Smrg   printf("  Display:     %p\n", (void *) h->Dpy);
41632001f49Smrg   printf("  Window:      0x%x\n", (int) h->Win);
41732001f49Smrg   printf("  Context:     0x%x\n", (int) h->Context);
41832001f49Smrg}
41932001f49Smrg#endif
42032001f49Smrg
42132001f49Smrg
42232001f49Smrgint
42332001f49Smrgmain(int argc, char *argv[])
42432001f49Smrg{
42532001f49Smrg   const char *dpyName = XDisplayName(NULL);
42632001f49Smrg
42732001f49Smrg   struct window *h0;
42832001f49Smrg
42932001f49Smrg   /* four windows and contexts sharing display lists and texture objects */
43032001f49Smrg   h0 = AddWindow(dpyName,  10,  10, NULL);
43132001f49Smrg   (void) AddWindow(dpyName, 330,  10, h0);
43232001f49Smrg   (void) AddWindow(dpyName,  10, 350, h0);
43332001f49Smrg   (void) AddWindow(dpyName, 330, 350, h0);
43432001f49Smrg
43532001f49Smrg   InitGLstuff(h0);
43632001f49Smrg
43732001f49Smrg   EventLoop();
43832001f49Smrg   return 0;
43932001f49Smrg}
440