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