1 /* $Id: sharedtex.c,v 1.2 2002/01/16 14:32:46 joukj Exp $ */
4 * Test sharing of display lists and texture objects between GLX contests.
9 * Copyright (C) 2000 Brian Paul All Rights Reserved.
11 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
18 * The above copyright notice and this permission notice shall be included
19 * in all copies or substantial portions of the Software.
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
25 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 * Modified 2009 for multithreading by Thomas Hellstrom.
42 struct thread_init_arg
{
47 pthread_mutex_t drawMutex
;
48 char DisplayName
[1000];
58 #define MAX_WINDOWS 20
59 static struct window Windows
[MAX_WINDOWS
];
60 static int NumWindows
= 0;
61 static int terminate
= 0;
62 static GLXContext gCtx
;
64 static GLuint Textures
[3];
69 Error(const char *display
, const char *msg
)
71 fprintf(stderr
, "Error on display %s - %s\n", display
, msg
);
77 initMainthread(Display
*dpy
, const char *displayName
)
81 int attrib
[] = { GLX_RGBA
,
89 scrnum
= DefaultScreen(dpy
);
90 visinfo
= glXChooseVisual(dpy
, scrnum
, attrib
);
92 Error(displayName
, "Unable to find RGB, double-buffered visual");
95 gCtx
= glXCreateContext(dpy
, visinfo
, NULL
, True
);
97 Error(displayName
, "Couldn't create GLX context");
103 static struct window
*
104 AddWindow(Display
*dpy
, const char *displayName
, int xpos
, int ypos
,
109 int attrib
[] = { GLX_RGBA
,
117 XSetWindowAttributes attr
;
120 XVisualInfo
*visinfo
;
121 int width
= 300, height
= 300;
123 if (NumWindows
>= MAX_WINDOWS
)
126 scrnum
= DefaultScreen(dpy
);
127 root
= RootWindow(dpy
, scrnum
);
129 visinfo
= glXChooseVisual(dpy
, scrnum
, attrib
);
131 Error(displayName
, "Unable to find RGB, double-buffered visual");
135 /* window attributes */
136 attr
.background_pixel
= 0;
137 attr
.border_pixel
= 0;
138 attr
.colormap
= XCreateColormap(dpy
, root
, visinfo
->visual
, AllocNone
);
139 attr
.event_mask
= StructureNotifyMask
| ExposureMask
| KeyPressMask
;
140 mask
= CWBorderPixel
| CWColormap
| CWEventMask
;
142 win
= XCreateWindow(dpy
, root
, xpos
, ypos
, width
, height
,
143 0, visinfo
->depth
, InputOutput
,
144 visinfo
->visual
, mask
, &attr
);
146 Error(displayName
, "Couldn't create window");
151 XSizeHints sizehints
;
154 sizehints
.width
= width
;
155 sizehints
.height
= height
;
156 sizehints
.flags
= USSize
| USPosition
;
157 XSetNormalHints(dpy
, win
, &sizehints
);
158 XSetStandardProperties(dpy
, win
, displayName
, displayName
,
159 None
, (char **)NULL
, 0, &sizehints
);
163 ctx
= glXCreateContext(dpy
, visinfo
,
164 sCtx
? sCtx
: NULL
, True
);
167 Error(displayName
, "Couldn't create GLX context");
171 XMapWindow(dpy
, win
);
173 /* save the info for this window */
176 struct window
*h
= &Windows
[NumWindows
];
177 strcpy(h
->DisplayName
, displayName
);
183 h
->visInfo
= visinfo
;
184 pthread_mutex_init(&h
->drawMutex
, NULL
);
186 return &Windows
[NumWindows
-1];
195 glGenTextures(3, Textures
);
197 /* setup first texture object */
199 GLubyte image
[16][16][4];
201 glBindTexture(GL_TEXTURE_2D
, Textures
[0]);
203 /* red/white checkerboard */
204 for (i
= 0; i
< 16; i
++) {
205 for (j
= 0; j
< 16; j
++) {
207 image
[i
][j
][0] = 255;
208 image
[i
][j
][1] = 255;
209 image
[i
][j
][2] = 255;
210 image
[i
][j
][3] = 255;
213 image
[i
][j
][0] = 255;
216 image
[i
][j
][3] = 255;
221 glPixelStorei(GL_UNPACK_ALIGNMENT
, 1);
222 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, 16, 16, 0, GL_RGBA
,
223 GL_UNSIGNED_BYTE
, image
);
224 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
225 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
228 /* setup second texture object */
230 GLubyte image
[8][8][3];
232 glBindTexture(GL_TEXTURE_2D
, Textures
[1]);
234 /* green/yellow checkerboard */
235 for (i
= 0; i
< 8; i
++) {
236 for (j
= 0; j
< 8; j
++) {
239 image
[i
][j
][1] = 255;
243 image
[i
][j
][0] = 255;
244 image
[i
][j
][1] = 255;
250 glPixelStorei(GL_UNPACK_ALIGNMENT
, 2);
251 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGB
, 8, 8, 0, GL_RGB
,
252 GL_UNSIGNED_BYTE
, image
);
253 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
254 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
257 /* setup second texture object */
259 GLubyte image
[4][4][3];
261 glBindTexture(GL_TEXTURE_2D
, Textures
[2]);
263 /* blue/gray checkerboard */
264 for (i
= 0; i
< 4; i
++) {
265 for (j
= 0; j
< 4; j
++) {
269 image
[i
][j
][2] = 255;
272 image
[i
][j
][0] = 200;
273 image
[i
][j
][1] = 200;
274 image
[i
][j
][2] = 200;
279 glPixelStorei(GL_UNPACK_ALIGNMENT
, 2);
280 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGB
, 4, 4, 0, GL_RGB
,
281 GL_UNSIGNED_BYTE
, image
);
282 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
283 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
286 /* Now make the cube object display list */
288 printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER
));
289 printf("GL_VERSION: %s\n", (char *) glGetString(GL_VERSION
));
290 printf("GL_VENDOR: %s\n", (char *) glGetString(GL_VENDOR
));
294 Redraw(struct window
*h
)
296 pthread_mutex_lock(&h
->drawMutex
);
297 if (!glXMakeCurrent(h
->Dpy
, h
->Win
, h
->Context
)) {
298 Error(h
->DisplayName
, "glXMakeCurrent failed in Redraw");
299 pthread_mutex_unlock(&h
->drawMutex
);
305 glShadeModel(GL_FLAT
);
306 glClearColor(0.25, 0.25, 0.25, 1.0);
307 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
309 glEnable(GL_TEXTURE_2D
);
310 glEnable(GL_DEPTH_TEST
);
311 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_REPLACE
);
317 glRotatef(h
->Angle
, 0, 1, -1);
319 glRotatef(-(h
->Angle
), 0, 1, -1);
321 glRotatef(h
->Angle
, 0, 1, 1);
323 glRotatef(-(h
->Angle
), 0, 1, 1);
324 glBindTexture(GL_TEXTURE_2D
, Textures
[0]);
326 glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
327 glTexCoord2f(1, 0); glVertex3f(-1, 1, -1);
328 glTexCoord2f(1, 1); glVertex3f(-1, 1, 1);
329 glTexCoord2f(0, 1); glVertex3f(-1, -1, 1);
332 glTexCoord2f(0, 0); glVertex3f(1, -1, -1);
333 glTexCoord2f(1, 0); glVertex3f(1, 1, -1);
334 glTexCoord2f(1, 1); glVertex3f(1, 1, 1);
335 glTexCoord2f(0, 1); glVertex3f(1, -1, 1);
338 glBindTexture(GL_TEXTURE_2D
, Textures
[1]);
340 glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
341 glTexCoord2f(1, 0); glVertex3f( 1, -1, -1);
342 glTexCoord2f(1, 1); glVertex3f( 1, -1, 1);
343 glTexCoord2f(0, 1); glVertex3f(-1, -1, 1);
346 glTexCoord2f(0, 0); glVertex3f(-1, 1, -1);
347 glTexCoord2f(1, 0); glVertex3f( 1, 1, -1);
348 glTexCoord2f(1, 1); glVertex3f( 1, 1, 1);
349 glTexCoord2f(0, 1); glVertex3f(-1, 1, 1);
352 glBindTexture(GL_TEXTURE_2D
, Textures
[2]);
354 glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
355 glTexCoord2f(1, 0); glVertex3f( 1, -1, -1);
356 glTexCoord2f(1, 1); glVertex3f( 1, 1, -1);
357 glTexCoord2f(0, 1); glVertex3f(-1, 1, -1);
360 glTexCoord2f(0, 0); glVertex3f(-1, -1, 1);
361 glTexCoord2f(1, 0); glVertex3f( 1, -1, 1);
362 glTexCoord2f(1, 1); glVertex3f( 1, 1, 1);
363 glTexCoord2f(0, 1); glVertex3f(-1, 1, 1);
368 glXSwapBuffers(h
->Dpy
, h
->Win
);
370 if (!glXMakeCurrent(h
->Dpy
, None
, NULL
)) {
371 Error(h
->DisplayName
, "glXMakeCurrent failed in Redraw");
373 pthread_mutex_unlock(&h
->drawMutex
);
376 static void *threadRunner (void *arg
)
378 struct thread_init_arg
*tia
= (struct thread_init_arg
*) arg
;
381 win
= &Windows
[tia
->id
];
392 Resize(struct window
*h
, unsigned int width
, unsigned int height
)
394 pthread_mutex_lock(&h
->drawMutex
);
396 if (!glXMakeCurrent(h
->Dpy
, h
->Win
, h
->Context
)) {
397 Error(h
->DisplayName
, "glXMakeCurrent failed in Resize()");
398 pthread_mutex_unlock(&h
->drawMutex
);
402 glViewport(0, 0, width
, height
);
403 glMatrixMode(GL_PROJECTION
);
405 glFrustum(-1, 1, -1, 1, 2, 10);
406 glMatrixMode(GL_MODELVIEW
);
408 glTranslatef(0, 0, -4.5);
409 if (!glXMakeCurrent(h
->Dpy
, None
, NULL
)) {
410 Error(h
->DisplayName
, "glXMakeCurrent failed in Resize()");
412 pthread_mutex_unlock(&h
->drawMutex
);
422 XNextEvent(gDpy
, &event
);
423 for (i
= 0; i
< NumWindows
; i
++) {
424 struct window
*h
= &Windows
[i
];
425 if (event
.xany
.window
== h
->Win
) {
426 switch (event
.type
) {
430 case ConfigureNotify
:
431 Resize(h
, event
.xconfigure
.width
, event
.xconfigure
.height
);
445 main(int argc
, char *argv
[])
447 const char *dpyName
= XDisplayName(NULL
);
448 pthread_t t0
, t1
, t2
, t3
;
449 struct thread_init_arg tia0
, tia1
, tia2
, tia3
;
454 gDpy
= XOpenDisplay(dpyName
);
456 Error(dpyName
, "Unable to open display");
460 if (initMainthread(gDpy
, dpyName
))
463 /* four windows and contexts sharing display lists and texture objects */
464 h0
= AddWindow(gDpy
, dpyName
, 10, 10, gCtx
);
465 (void) AddWindow(gDpy
, dpyName
, 330, 10, gCtx
);
466 (void) AddWindow(gDpy
, dpyName
, 10, 350, gCtx
);
467 (void) AddWindow(gDpy
, dpyName
, 330, 350, gCtx
);
469 if (!glXMakeCurrent(gDpy
, h0
->Win
, gCtx
)) {
470 Error(dpyName
, "glXMakeCurrent failed for init thread.");
477 pthread_create(&t0
, NULL
, threadRunner
, &tia0
);
479 pthread_create(&t1
, NULL
, threadRunner
, &tia1
);
481 pthread_create(&t2
, NULL
, threadRunner
, &tia2
);
483 pthread_create(&t3
, NULL
, threadRunner
, &tia3
);