3 * Test sharing of display lists and texture objects between GLX contests.
8 * Copyright (C) 2000 Brian Paul All Rights Reserved.
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:
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
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.
38 char DisplayName
[1000];
47 #define MAX_WINDOWS 20
48 static struct window Windows
[MAX_WINDOWS
];
49 static int NumWindows
= 0;
52 static GLuint Textures
[3];
53 static GLuint CubeList
;
58 Error(const char *display
, const char *msg
)
60 fprintf(stderr
, "Error on display %s - %s\n", display
, msg
);
65 static struct window
*
66 AddWindow(const char *displayName
, int xpos
, int ypos
,
67 const struct window
*shareWindow
)
72 int attrib
[] = { GLX_RGBA
,
80 XSetWindowAttributes attr
;
84 int width
= 300, height
= 300;
86 if (NumWindows
>= MAX_WINDOWS
)
89 dpy
= XOpenDisplay(displayName
);
91 Error(displayName
, "Unable to open display");
95 scrnum
= DefaultScreen(dpy
);
96 root
= RootWindow(dpy
, scrnum
);
98 visinfo
= glXChooseVisual(dpy
, scrnum
, attrib
);
100 Error(displayName
, "Unable to find RGB, double-buffered visual");
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
;
111 win
= XCreateWindow(dpy
, root
, xpos
, ypos
, width
, height
,
112 0, visinfo
->depth
, InputOutput
,
113 visinfo
->visual
, mask
, &attr
);
115 Error(displayName
, "Couldn't create window");
120 XSizeHints sizehints
;
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
);
132 ctx
= glXCreateContext(dpy
, visinfo
,
133 shareWindow
? shareWindow
->Context
: NULL
,
136 Error(displayName
, "Couldn't create GLX context");
140 XMapWindow(dpy
, win
);
142 if (!glXMakeCurrent(dpy
, win
, ctx
)) {
143 Error(displayName
, "glXMakeCurrent failed");
144 printf("glXMakeCurrent failed in Redraw()\n");
148 /* save the info for this window */
151 struct window
*h
= &Windows
[NumWindows
];
152 strcpy(h
->DisplayName
, displayName
);
159 return &Windows
[NumWindows
-1];
166 InitGLstuff(struct window
*h
)
168 if (!glXMakeCurrent(h
->Dpy
, h
->Win
, h
->Context
)) {
169 Error(h
->DisplayName
, "glXMakeCurrent failed in InitGLstuff");
173 glGenTextures(3, Textures
);
175 /* setup first texture object */
177 GLubyte image
[16][16][4];
179 glBindTexture(GL_TEXTURE_2D
, Textures
[0]);
181 /* red/white checkerboard */
182 for (i
= 0; i
< 16; i
++) {
183 for (j
= 0; j
< 16; j
++) {
185 image
[i
][j
][0] = 255;
186 image
[i
][j
][1] = 255;
187 image
[i
][j
][2] = 255;
188 image
[i
][j
][3] = 255;
191 image
[i
][j
][0] = 255;
194 image
[i
][j
][3] = 255;
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
);
206 /* setup second texture object */
208 GLubyte image
[8][8][3];
210 glBindTexture(GL_TEXTURE_2D
, Textures
[1]);
212 /* green/yellow checkerboard */
213 for (i
= 0; i
< 8; i
++) {
214 for (j
= 0; j
< 8; j
++) {
217 image
[i
][j
][1] = 255;
221 image
[i
][j
][0] = 255;
222 image
[i
][j
][1] = 255;
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
);
235 /* setup second texture object */
237 GLubyte image
[4][4][3];
239 glBindTexture(GL_TEXTURE_2D
, Textures
[2]);
241 /* blue/gray checkerboard */
242 for (i
= 0; i
< 4; i
++) {
243 for (j
= 0; j
< 4; j
++) {
247 image
[i
][j
][2] = 255;
250 image
[i
][j
][0] = 200;
251 image
[i
][j
][1] = 200;
252 image
[i
][j
][2] = 200;
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
);
264 /* Now make the cube object display list */
265 CubeList
= glGenLists(1);
266 glNewList(CubeList
, GL_COMPILE
);
268 glBindTexture(GL_TEXTURE_2D
, Textures
[0]);
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);
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);
282 glBindTexture(GL_TEXTURE_2D
, Textures
[1]);
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);
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);
296 glBindTexture(GL_TEXTURE_2D
, Textures
[2]);
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);
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);
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
));
320 Redraw(struct window
*h
)
322 if (!glXMakeCurrent(h
->Dpy
, h
->Win
, h
->Context
)) {
323 Error(h
->DisplayName
, "glXMakeCurrent failed");
324 printf("glXMakeCurrent failed in Redraw()\n");
330 glShadeModel(GL_FLAT
);
331 glClearColor(0.25, 0.25, 0.25, 1.0);
332 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
334 glEnable(GL_TEXTURE_2D
);
335 glEnable(GL_DEPTH_TEST
);
336 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_REPLACE
);
342 glRotatef(h
->Angle
, 0, 1, -1);
344 glRotatef(-(h
->Angle
), 0, 1, -1);
346 glRotatef(h
->Angle
, 0, 1, 1);
348 glRotatef(-(h
->Angle
), 0, 1, 1);
349 glCallList(CubeList
);
352 glXSwapBuffers(h
->Dpy
, h
->Win
);
358 Resize(const struct window
*h
, unsigned int width
, unsigned int height
)
360 if (!glXMakeCurrent(h
->Dpy
, h
->Win
, h
->Context
)) {
361 Error(h
->DisplayName
, "glXMakeCurrent failed in Resize()");
364 glViewport(0, 0, width
, height
);
365 glMatrixMode(GL_PROJECTION
);
367 glFrustum(-1, 1, -1, 1, 2, 10);
368 glMatrixMode(GL_MODELVIEW
);
370 glTranslatef(0, 0, -4.5);
380 for (i
= 0; i
< NumWindows
; i
++) {
381 struct window
*h
= &Windows
[i
];
382 while (XPending(h
->Dpy
) > 0) {
384 XNextEvent(h
->Dpy
, &event
);
385 if (event
.xany
.window
== h
->Win
) {
386 switch (event
.type
) {
390 case ConfigureNotify
:
391 Resize(h
, event
.xconfigure
.width
, event
.xconfigure
.height
);
400 printf("window mismatch\n");
412 PrintInfo(const struct window
*h
)
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
);
423 main(int argc
, char *argv
[])
425 const char *dpyName
= XDisplayName(NULL
);
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
);