1 2/* 3 * Test sharing of display lists and texture objects between GLX contests. 4 * Brian Paul 5 * Summer 2000 6 * 7 * 8 * Copyright (C) 2000 Brian Paul All Rights Reserved. 9 * 10 * Permission is hereby granted, free of charge, to any person obtaining a 11 * copy of this software and associated documentation files (the "Software"), 12 * to deal in the Software without restriction, including without limitation 13 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 * and/or sell copies of the Software, and to permit persons to whom the 15 * Software is furnished to do so, subject to the following conditions: 16 * 17 * The above copyright notice and this permission notice shall be included 18 * in all copies or substantial portions of the Software. 19 * 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 24 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 */ 27 28 29#include <GL/gl.h> 30#include <GL/glx.h> 31#include <stdio.h> 32#include <stdlib.h> 33#include <unistd.h> 34#include <string.h> 35 36 37struct window { 38 char DisplayName[1000]; 39 Display *Dpy; 40 Window Win; 41 GLXContext Context; 42 float Angle; 43 int Id; 44}; 45 46 47#define MAX_WINDOWS 20 48static struct window Windows[MAX_WINDOWS]; 49static int NumWindows = 0; 50 51 52static GLuint Textures[3]; 53static GLuint CubeList; 54 55 56 57static void 58Error(const char *display, const char *msg) 59{ 60 fprintf(stderr, "Error on display %s - %s\n", display, msg); 61 exit(1); 62} 63 64 65static struct window * 66AddWindow(const char *displayName, int xpos, int ypos, 67 const struct window *shareWindow) 68{ 69 Display *dpy; 70 Window win; 71 GLXContext ctx; 72 int attrib[] = { GLX_RGBA, 73 GLX_RED_SIZE, 1, 74 GLX_GREEN_SIZE, 1, 75 GLX_BLUE_SIZE, 1, 76 GLX_DOUBLEBUFFER, 77 GLX_DEPTH_SIZE, 1, 78 None }; 79 int scrnum; 80 XSetWindowAttributes attr; 81 unsigned long mask; 82 Window root; 83 XVisualInfo *visinfo; 84 int width = 300, height = 300; 85 86 if (NumWindows >= MAX_WINDOWS) 87 return NULL; 88 89 dpy = XOpenDisplay(displayName); 90 if (!dpy) { 91 Error(displayName, "Unable to open display"); 92 return NULL; 93 } 94 95 scrnum = DefaultScreen(dpy); 96 root = RootWindow(dpy, scrnum); 97 98 visinfo = glXChooseVisual(dpy, scrnum, attrib); 99 if (!visinfo) { 100 Error(displayName, "Unable to find RGB, double-buffered visual"); 101 return NULL; 102 } 103 104 /* window attributes */ 105 attr.background_pixel = 0; 106 attr.border_pixel = 0; 107 attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone); 108 attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; 109 mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; 110 111 win = XCreateWindow(dpy, root, xpos, ypos, width, height, 112 0, visinfo->depth, InputOutput, 113 visinfo->visual, mask, &attr); 114 if (!win) { 115 Error(displayName, "Couldn't create window"); 116 return NULL; 117 } 118 119 { 120 XSizeHints sizehints; 121 sizehints.x = xpos; 122 sizehints.y = ypos; 123 sizehints.width = width; 124 sizehints.height = height; 125 sizehints.flags = USSize | USPosition; 126 XSetNormalHints(dpy, win, &sizehints); 127 XSetStandardProperties(dpy, win, displayName, displayName, 128 None, (char **)NULL, 0, &sizehints); 129 } 130 131 132 ctx = glXCreateContext(dpy, visinfo, 133 shareWindow ? shareWindow->Context : NULL, 134 True); 135 if (!ctx) { 136 Error(displayName, "Couldn't create GLX context"); 137 return NULL; 138 } 139 140 XMapWindow(dpy, win); 141 142 if (!glXMakeCurrent(dpy, win, ctx)) { 143 Error(displayName, "glXMakeCurrent failed"); 144 printf("glXMakeCurrent failed in Redraw()\n"); 145 return NULL; 146 } 147 148 /* save the info for this window */ 149 { 150 static int id = 0; 151 struct window *h = &Windows[NumWindows]; 152 strcpy(h->DisplayName, displayName); 153 h->Dpy = dpy; 154 h->Win = win; 155 h->Context = ctx; 156 h->Angle = 0.0; 157 h->Id = id++; 158 NumWindows++; 159 return &Windows[NumWindows-1]; 160 } 161 162} 163 164 165static void 166InitGLstuff(struct window *h) 167{ 168 if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) { 169 Error(h->DisplayName, "glXMakeCurrent failed in InitGLstuff"); 170 return; 171 } 172 173 glGenTextures(3, Textures); 174 175 /* setup first texture object */ 176 { 177 GLubyte image[16][16][4]; 178 GLint i, j; 179 glBindTexture(GL_TEXTURE_2D, Textures[0]); 180 181 /* red/white checkerboard */ 182 for (i = 0; i < 16; i++) { 183 for (j = 0; j < 16; j++) { 184 if ((i ^ j) & 1) { 185 image[i][j][0] = 255; 186 image[i][j][1] = 255; 187 image[i][j][2] = 255; 188 image[i][j][3] = 255; 189 } 190 else { 191 image[i][j][0] = 255; 192 image[i][j][1] = 0; 193 image[i][j][2] = 0; 194 image[i][j][3] = 255; 195 } 196 } 197 } 198 199 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 200 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, 201 GL_UNSIGNED_BYTE, image); 202 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 203 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 204 } 205 206 /* setup second texture object */ 207 { 208 GLubyte image[8][8][3]; 209 GLint i, j; 210 glBindTexture(GL_TEXTURE_2D, Textures[1]); 211 212 /* green/yellow checkerboard */ 213 for (i = 0; i < 8; i++) { 214 for (j = 0; j < 8; j++) { 215 if ((i ^ j) & 1) { 216 image[i][j][0] = 0; 217 image[i][j][1] = 255; 218 image[i][j][2] = 0; 219 } 220 else { 221 image[i][j][0] = 255; 222 image[i][j][1] = 255; 223 image[i][j][2] = 0; 224 } 225 } 226 } 227 228 glPixelStorei(GL_UNPACK_ALIGNMENT, 2); 229 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, 230 GL_UNSIGNED_BYTE, image); 231 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 232 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 233 } 234 235 /* setup second texture object */ 236 { 237 GLubyte image[4][4][3]; 238 GLint i, j; 239 glBindTexture(GL_TEXTURE_2D, Textures[2]); 240 241 /* blue/gray checkerboard */ 242 for (i = 0; i < 4; i++) { 243 for (j = 0; j < 4; j++) { 244 if ((i ^ j) & 1) { 245 image[i][j][0] = 0; 246 image[i][j][1] = 0; 247 image[i][j][2] = 255; 248 } 249 else { 250 image[i][j][0] = 200; 251 image[i][j][1] = 200; 252 image[i][j][2] = 200; 253 } 254 } 255 } 256 257 glPixelStorei(GL_UNPACK_ALIGNMENT, 2); 258 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 4, 4, 0, GL_RGB, 259 GL_UNSIGNED_BYTE, image); 260 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 261 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 262 } 263 264 /* Now make the cube object display list */ 265 CubeList = glGenLists(1); 266 glNewList(CubeList, GL_COMPILE); 267 { 268 glBindTexture(GL_TEXTURE_2D, Textures[0]); 269 glBegin(GL_POLYGON); 270 glTexCoord2f(0, 0); glVertex3f(-1, -1, -1); 271 glTexCoord2f(1, 0); glVertex3f(-1, 1, -1); 272 glTexCoord2f(1, 1); glVertex3f(-1, 1, 1); 273 glTexCoord2f(0, 1); glVertex3f(-1, -1, 1); 274 glEnd(); 275 glBegin(GL_POLYGON); 276 glTexCoord2f(0, 0); glVertex3f(1, -1, -1); 277 glTexCoord2f(1, 0); glVertex3f(1, 1, -1); 278 glTexCoord2f(1, 1); glVertex3f(1, 1, 1); 279 glTexCoord2f(0, 1); glVertex3f(1, -1, 1); 280 glEnd(); 281 282 glBindTexture(GL_TEXTURE_2D, Textures[1]); 283 glBegin(GL_POLYGON); 284 glTexCoord2f(0, 0); glVertex3f(-1, -1, -1); 285 glTexCoord2f(1, 0); glVertex3f( 1, -1, -1); 286 glTexCoord2f(1, 1); glVertex3f( 1, -1, 1); 287 glTexCoord2f(0, 1); glVertex3f(-1, -1, 1); 288 glEnd(); 289 glBegin(GL_POLYGON); 290 glTexCoord2f(0, 0); glVertex3f(-1, 1, -1); 291 glTexCoord2f(1, 0); glVertex3f( 1, 1, -1); 292 glTexCoord2f(1, 1); glVertex3f( 1, 1, 1); 293 glTexCoord2f(0, 1); glVertex3f(-1, 1, 1); 294 glEnd(); 295 296 glBindTexture(GL_TEXTURE_2D, Textures[2]); 297 glBegin(GL_POLYGON); 298 glTexCoord2f(0, 0); glVertex3f(-1, -1, -1); 299 glTexCoord2f(1, 0); glVertex3f( 1, -1, -1); 300 glTexCoord2f(1, 1); glVertex3f( 1, 1, -1); 301 glTexCoord2f(0, 1); glVertex3f(-1, 1, -1); 302 glEnd(); 303 glBegin(GL_POLYGON); 304 glTexCoord2f(0, 0); glVertex3f(-1, -1, 1); 305 glTexCoord2f(1, 0); glVertex3f( 1, -1, 1); 306 glTexCoord2f(1, 1); glVertex3f( 1, 1, 1); 307 glTexCoord2f(0, 1); glVertex3f(-1, 1, 1); 308 glEnd(); 309 } 310 glEndList(); 311 312 printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER)); 313 printf("GL_VERSION: %s\n", (char *) glGetString(GL_VERSION)); 314 printf("GL_VENDOR: %s\n", (char *) glGetString(GL_VENDOR)); 315} 316 317 318 319static void 320Redraw(struct window *h) 321{ 322 if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) { 323 Error(h->DisplayName, "glXMakeCurrent failed"); 324 printf("glXMakeCurrent failed in Redraw()\n"); 325 return; 326 } 327 328 h->Angle += 1.0; 329 330 glShadeModel(GL_FLAT); 331 glClearColor(0.25, 0.25, 0.25, 1.0); 332 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 333 334 glEnable(GL_TEXTURE_2D); 335 glEnable(GL_DEPTH_TEST); 336 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 337 338 glColor3f(1, 1, 1); 339 340 glPushMatrix(); 341 if (h->Id == 0) 342 glRotatef(h->Angle, 0, 1, -1); 343 else if (h->Id == 1) 344 glRotatef(-(h->Angle), 0, 1, -1); 345 else if (h->Id == 2) 346 glRotatef(h->Angle, 0, 1, 1); 347 else if (h->Id == 3) 348 glRotatef(-(h->Angle), 0, 1, 1); 349 glCallList(CubeList); 350 glPopMatrix(); 351 352 glXSwapBuffers(h->Dpy, h->Win); 353} 354 355 356 357static void 358Resize(const struct window *h, unsigned int width, unsigned int height) 359{ 360 if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) { 361 Error(h->DisplayName, "glXMakeCurrent failed in Resize()"); 362 return; 363 } 364 glViewport(0, 0, width, height); 365 glMatrixMode(GL_PROJECTION); 366 glLoadIdentity(); 367 glFrustum(-1, 1, -1, 1, 2, 10); 368 glMatrixMode(GL_MODELVIEW); 369 glLoadIdentity(); 370 glTranslatef(0, 0, -4.5); 371} 372 373 374 375static void 376EventLoop(void) 377{ 378 while (1) { 379 int i; 380 for (i = 0; i < NumWindows; i++) { 381 struct window *h = &Windows[i]; 382 while (XPending(h->Dpy) > 0) { 383 XEvent event; 384 XNextEvent(h->Dpy, &event); 385 if (event.xany.window == h->Win) { 386 switch (event.type) { 387 case Expose: 388 Redraw(h); 389 break; 390 case ConfigureNotify: 391 Resize(h, event.xconfigure.width, event.xconfigure.height); 392 break; 393 case KeyPress: 394 return; 395 default: 396 /*no-op*/ ; 397 } 398 } 399 else { 400 printf("window mismatch\n"); 401 } 402 } 403 Redraw(h); 404 } 405 usleep(1); 406 } 407} 408 409 410#if 0 411static void 412PrintInfo(const struct window *h) 413{ 414 printf("Name: %s\n", h->DisplayName); 415 printf(" Display: %p\n", (void *) h->Dpy); 416 printf(" Window: 0x%x\n", (int) h->Win); 417 printf(" Context: 0x%x\n", (int) h->Context); 418} 419#endif 420 421 422int 423main(int argc, char *argv[]) 424{ 425 const char *dpyName = XDisplayName(NULL); 426 427 struct window *h0; 428 429 /* four windows and contexts sharing display lists and texture objects */ 430 h0 = AddWindow(dpyName, 10, 10, NULL); 431 (void) AddWindow(dpyName, 330, 10, h0); 432 (void) AddWindow(dpyName, 10, 350, h0); 433 (void) AddWindow(dpyName, 330, 350, h0); 434 435 InitGLstuff(h0); 436 437 EventLoop(); 438 return 0; 439} 440