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 if (strlen(displayName
) + 1 > sizeof(h
->DisplayName
)) {
178 Error(displayName
, "string overflow");
181 strcpy(h
->DisplayName
, displayName
);
187 h
->visInfo
= visinfo
;
188 pthread_mutex_init(&h
->drawMutex
, NULL
);
190 return &Windows
[NumWindows
-1];
199 glGenTextures(3, Textures
);
201 /* setup first texture object */
203 GLubyte image
[16][16][4];
205 glBindTexture(GL_TEXTURE_2D
, Textures
[0]);
207 /* red/white checkerboard */
208 for (i
= 0; i
< 16; i
++) {
209 for (j
= 0; j
< 16; j
++) {
211 image
[i
][j
][0] = 255;
212 image
[i
][j
][1] = 255;
213 image
[i
][j
][2] = 255;
214 image
[i
][j
][3] = 255;
217 image
[i
][j
][0] = 255;
220 image
[i
][j
][3] = 255;
225 glPixelStorei(GL_UNPACK_ALIGNMENT
, 1);
226 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, 16, 16, 0, GL_RGBA
,
227 GL_UNSIGNED_BYTE
, image
);
228 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
229 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
232 /* setup second texture object */
234 GLubyte image
[8][8][3];
236 glBindTexture(GL_TEXTURE_2D
, Textures
[1]);
238 /* green/yellow checkerboard */
239 for (i
= 0; i
< 8; i
++) {
240 for (j
= 0; j
< 8; j
++) {
243 image
[i
][j
][1] = 255;
247 image
[i
][j
][0] = 255;
248 image
[i
][j
][1] = 255;
254 glPixelStorei(GL_UNPACK_ALIGNMENT
, 2);
255 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGB
, 8, 8, 0, GL_RGB
,
256 GL_UNSIGNED_BYTE
, image
);
257 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
258 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
261 /* setup second texture object */
263 GLubyte image
[4][4][3];
265 glBindTexture(GL_TEXTURE_2D
, Textures
[2]);
267 /* blue/gray checkerboard */
268 for (i
= 0; i
< 4; i
++) {
269 for (j
= 0; j
< 4; j
++) {
273 image
[i
][j
][2] = 255;
276 image
[i
][j
][0] = 200;
277 image
[i
][j
][1] = 200;
278 image
[i
][j
][2] = 200;
283 glPixelStorei(GL_UNPACK_ALIGNMENT
, 2);
284 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGB
, 4, 4, 0, GL_RGB
,
285 GL_UNSIGNED_BYTE
, image
);
286 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
287 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
290 /* Now make the cube object display list */
292 printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER
));
293 printf("GL_VERSION: %s\n", (char *) glGetString(GL_VERSION
));
294 printf("GL_VENDOR: %s\n", (char *) glGetString(GL_VENDOR
));
298 Redraw(struct window
*h
)
300 pthread_mutex_lock(&h
->drawMutex
);
301 if (!glXMakeCurrent(h
->Dpy
, h
->Win
, h
->Context
)) {
302 Error(h
->DisplayName
, "glXMakeCurrent failed in Redraw");
303 pthread_mutex_unlock(&h
->drawMutex
);
309 glShadeModel(GL_FLAT
);
310 glClearColor(0.25, 0.25, 0.25, 1.0);
311 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
313 glEnable(GL_TEXTURE_2D
);
314 glEnable(GL_DEPTH_TEST
);
315 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_REPLACE
);
321 glRotatef(h
->Angle
, 0, 1, -1);
323 glRotatef(-(h
->Angle
), 0, 1, -1);
325 glRotatef(h
->Angle
, 0, 1, 1);
327 glRotatef(-(h
->Angle
), 0, 1, 1);
328 glBindTexture(GL_TEXTURE_2D
, Textures
[0]);
330 glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
331 glTexCoord2f(1, 0); glVertex3f(-1, 1, -1);
332 glTexCoord2f(1, 1); glVertex3f(-1, 1, 1);
333 glTexCoord2f(0, 1); glVertex3f(-1, -1, 1);
336 glTexCoord2f(0, 0); glVertex3f(1, -1, -1);
337 glTexCoord2f(1, 0); glVertex3f(1, 1, -1);
338 glTexCoord2f(1, 1); glVertex3f(1, 1, 1);
339 glTexCoord2f(0, 1); glVertex3f(1, -1, 1);
342 glBindTexture(GL_TEXTURE_2D
, Textures
[1]);
344 glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
345 glTexCoord2f(1, 0); glVertex3f( 1, -1, -1);
346 glTexCoord2f(1, 1); glVertex3f( 1, -1, 1);
347 glTexCoord2f(0, 1); glVertex3f(-1, -1, 1);
350 glTexCoord2f(0, 0); glVertex3f(-1, 1, -1);
351 glTexCoord2f(1, 0); glVertex3f( 1, 1, -1);
352 glTexCoord2f(1, 1); glVertex3f( 1, 1, 1);
353 glTexCoord2f(0, 1); glVertex3f(-1, 1, 1);
356 glBindTexture(GL_TEXTURE_2D
, Textures
[2]);
358 glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
359 glTexCoord2f(1, 0); glVertex3f( 1, -1, -1);
360 glTexCoord2f(1, 1); glVertex3f( 1, 1, -1);
361 glTexCoord2f(0, 1); glVertex3f(-1, 1, -1);
364 glTexCoord2f(0, 0); glVertex3f(-1, -1, 1);
365 glTexCoord2f(1, 0); glVertex3f( 1, -1, 1);
366 glTexCoord2f(1, 1); glVertex3f( 1, 1, 1);
367 glTexCoord2f(0, 1); glVertex3f(-1, 1, 1);
372 glXSwapBuffers(h
->Dpy
, h
->Win
);
374 if (!glXMakeCurrent(h
->Dpy
, None
, NULL
)) {
375 Error(h
->DisplayName
, "glXMakeCurrent failed in Redraw");
377 pthread_mutex_unlock(&h
->drawMutex
);
380 static void *threadRunner (void *arg
)
382 struct thread_init_arg
*tia
= (struct thread_init_arg
*) arg
;
385 win
= &Windows
[tia
->id
];
396 Resize(struct window
*h
, unsigned int width
, unsigned int height
)
398 pthread_mutex_lock(&h
->drawMutex
);
400 if (!glXMakeCurrent(h
->Dpy
, h
->Win
, h
->Context
)) {
401 Error(h
->DisplayName
, "glXMakeCurrent failed in Resize()");
402 pthread_mutex_unlock(&h
->drawMutex
);
406 glViewport(0, 0, width
, height
);
407 glMatrixMode(GL_PROJECTION
);
409 glFrustum(-1, 1, -1, 1, 2, 10);
410 glMatrixMode(GL_MODELVIEW
);
412 glTranslatef(0, 0, -4.5);
413 if (!glXMakeCurrent(h
->Dpy
, None
, NULL
)) {
414 Error(h
->DisplayName
, "glXMakeCurrent failed in Resize()");
416 pthread_mutex_unlock(&h
->drawMutex
);
426 XNextEvent(gDpy
, &event
);
427 for (i
= 0; i
< NumWindows
; i
++) {
428 struct window
*h
= &Windows
[i
];
429 if (event
.xany
.window
== h
->Win
) {
430 switch (event
.type
) {
434 case ConfigureNotify
:
435 Resize(h
, event
.xconfigure
.width
, event
.xconfigure
.height
);
449 main(int argc
, char *argv
[])
451 const char *dpyName
= XDisplayName(NULL
);
452 pthread_t t0
, t1
, t2
, t3
;
453 struct thread_init_arg tia0
, tia1
, tia2
, tia3
;
458 gDpy
= XOpenDisplay(dpyName
);
460 Error(dpyName
, "Unable to open display");
464 if (initMainthread(gDpy
, dpyName
))
467 /* four windows and contexts sharing display lists and texture objects */
468 h0
= AddWindow(gDpy
, dpyName
, 10, 10, gCtx
);
469 (void) AddWindow(gDpy
, dpyName
, 330, 10, gCtx
);
470 (void) AddWindow(gDpy
, dpyName
, 10, 350, gCtx
);
471 (void) AddWindow(gDpy
, dpyName
, 330, 350, gCtx
);
473 if (!glXMakeCurrent(gDpy
, h0
->Win
, gCtx
)) {
474 Error(dpyName
, "glXMakeCurrent failed for init thread.");
481 pthread_create(&t0
, NULL
, threadRunner
, &tia0
);
483 pthread_create(&t1
, NULL
, threadRunner
, &tia1
);
485 pthread_create(&t2
, NULL
, threadRunner
, &tia2
);
487 pthread_create(&t3
, NULL
, threadRunner
, &tia3
);