2 * Test sharing of display lists and texture objects between GLX contests.
7 * Copyright (C) 2000 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 * Modified 2009 for multithreading by Thomas Hellstrom.
29 * Port to windows by Michal Krol.
39 #pragma comment(lib, "opengl32.lib")
41 struct thread_init_arg
{
46 CRITICAL_SECTION drawMutex
;
53 HANDLE hEventInitialised
;
57 #define MAX_WINDOWS 20
58 static struct window Windows
[MAX_WINDOWS
];
59 static int NumWindows
= 0;
60 static HANDLE terminate
= NULL
;
61 static HGLRC gCtx
= NULL
;
62 static HDC gHDC
= NULL
;
63 static GLuint Textures
[3];
68 Error(const char *msg
)
70 fprintf(stderr
, "Error - %s\n", msg
);
75 Resize(struct window
*h
, unsigned int width
, unsigned int height
);
77 static LRESULT CALLBACK
89 LONG_PTR index
= GetWindowLongPtr(hWnd
, GWLP_USERDATA
);
91 if (index
>= 0 && index
< MAX_WINDOWS
) {
94 GetClientRect(hWnd
, &r
);
95 Resize(&Windows
[index
], r
.right
, r
.bottom
);
101 CREATESTRUCT
*pcs
= (CREATESTRUCT
*) lParam
;
103 SetWindowLongPtr(hWnd
, GWLP_USERDATA
, (LONG_PTR
) pcs
->lpCreateParams
);
110 return DefWindowProc(hWnd
, uMsg
, wParam
, lParam
);
121 PIXELFORMATDESCRIPTOR pfd
= {0};
124 wc
.lpfnWndProc
= WndProc
;
125 wc
.lpszClassName
= "sharedtex_mt.hidden";
126 wc
.style
= CS_OWNDC
| CS_HREDRAW
| CS_VREDRAW
;
129 win
= CreateWindowEx(0,
131 "sharedtex_mt.hidden",
132 WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
,
142 Error("Couldn't create window");
147 Error("Couldn't obtain HDC");
152 pfd
.dwFlags
= PFD_DOUBLEBUFFER
| PFD_DRAW_TO_WINDOW
| PFD_SUPPORT_OPENGL
;
153 pfd
.iLayerType
= PFD_MAIN_PLANE
;
154 pfd
.iPixelType
= PFD_TYPE_RGBA
;
155 pfd
.nSize
= sizeof(pfd
);
158 visinfo
= ChoosePixelFormat(gHDC
, &pfd
);
160 Error("Unable to find RGB, Z, double-buffered visual");
163 SetPixelFormat(gHDC
, visinfo
, &pfd
);
164 gCtx
= wglCreateContext(gHDC
);
166 Error("Couldn't create WGL context");
172 static struct window
*
173 AddWindow(int xpos
, int ypos
, HGLRC sCtx
)
175 struct window
*win
= &Windows
[NumWindows
];
177 int width
= 300, height
= 300;
179 if (NumWindows
>= MAX_WINDOWS
)
182 memset(win
, 0, sizeof(*win
));
183 InitializeCriticalSection(&win
->drawMutex
);
185 win
->Id
= NumWindows
++;
187 wc
.hbrBackground
= (HBRUSH
) (COLOR_BTNFACE
+ 1);
188 wc
.hCursor
= LoadCursor(NULL
, IDC_ARROW
);
189 wc
.hIcon
= LoadIcon(NULL
, IDI_APPLICATION
);
190 wc
.lpfnWndProc
= WndProc
;
191 wc
.lpszClassName
= "sharedtex_mt";
192 wc
.style
= CS_OWNDC
| CS_HREDRAW
| CS_VREDRAW
;
195 win
->Win
= CreateWindowEx(0,
198 WS_SIZEBOX
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
,
208 Error("Couldn't create window");
211 win
->sharedContext
= sCtx
;
213 ShowWindow(win
->Win
, SW_SHOW
);
222 glGenTextures(3, Textures
);
224 /* setup first texture object */
226 GLubyte image
[16][16][4];
228 glBindTexture(GL_TEXTURE_2D
, Textures
[0]);
230 /* red/white checkerboard */
231 for (i
= 0; i
< 16; i
++) {
232 for (j
= 0; j
< 16; j
++) {
234 image
[i
][j
][0] = 255;
235 image
[i
][j
][1] = 255;
236 image
[i
][j
][2] = 255;
237 image
[i
][j
][3] = 255;
240 image
[i
][j
][0] = 255;
243 image
[i
][j
][3] = 255;
248 glPixelStorei(GL_UNPACK_ALIGNMENT
, 1);
249 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, 16, 16, 0, GL_RGBA
,
250 GL_UNSIGNED_BYTE
, image
);
251 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
252 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
255 /* setup second texture object */
257 GLubyte image
[8][8][3];
259 glBindTexture(GL_TEXTURE_2D
, Textures
[1]);
261 /* green/yellow checkerboard */
262 for (i
= 0; i
< 8; i
++) {
263 for (j
= 0; j
< 8; j
++) {
266 image
[i
][j
][1] = 255;
270 image
[i
][j
][0] = 255;
271 image
[i
][j
][1] = 255;
277 glPixelStorei(GL_UNPACK_ALIGNMENT
, 2);
278 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGB
, 8, 8, 0, GL_RGB
,
279 GL_UNSIGNED_BYTE
, image
);
280 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
281 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
284 /* setup second texture object */
286 GLubyte image
[4][4][3];
288 glBindTexture(GL_TEXTURE_2D
, Textures
[2]);
290 /* blue/gray checkerboard */
291 for (i
= 0; i
< 4; i
++) {
292 for (j
= 0; j
< 4; j
++) {
296 image
[i
][j
][2] = 255;
299 image
[i
][j
][0] = 200;
300 image
[i
][j
][1] = 200;
301 image
[i
][j
][2] = 200;
306 glPixelStorei(GL_UNPACK_ALIGNMENT
, 2);
307 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGB
, 4, 4, 0, GL_RGB
,
308 GL_UNSIGNED_BYTE
, image
);
309 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
310 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
313 /* Now make the cube object display list */
315 printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER
));
316 printf("GL_VERSION: %s\n", (char *) glGetString(GL_VERSION
));
317 printf("GL_VENDOR: %s\n", (char *) glGetString(GL_VENDOR
));
321 Redraw(struct window
*h
)
323 EnterCriticalSection(&h
->drawMutex
);
324 if (!wglMakeCurrent(h
->hDC
, h
->Context
)) {
325 LeaveCriticalSection(&h
->drawMutex
);
326 Error("wglMakeCurrent failed in Redraw");
332 glShadeModel(GL_FLAT
);
333 glClearColor(0.25, 0.25, 0.25, 1.0);
334 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
336 glEnable(GL_TEXTURE_2D
);
337 glEnable(GL_DEPTH_TEST
);
338 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_REPLACE
);
344 glRotatef(h
->Angle
, 0, 1, -1);
346 glRotatef(-(h
->Angle
), 0, 1, -1);
348 glRotatef(h
->Angle
, 0, 1, 1);
350 glRotatef(-(h
->Angle
), 0, 1, 1);
351 glBindTexture(GL_TEXTURE_2D
, Textures
[0]);
353 glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
354 glTexCoord2f(1, 0); glVertex3f(-1, 1, -1);
355 glTexCoord2f(1, 1); glVertex3f(-1, 1, 1);
356 glTexCoord2f(0, 1); glVertex3f(-1, -1, 1);
359 glTexCoord2f(0, 0); glVertex3f(1, -1, -1);
360 glTexCoord2f(1, 0); glVertex3f(1, 1, -1);
361 glTexCoord2f(1, 1); glVertex3f(1, 1, 1);
362 glTexCoord2f(0, 1); glVertex3f(1, -1, 1);
365 glBindTexture(GL_TEXTURE_2D
, Textures
[1]);
367 glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
368 glTexCoord2f(1, 0); glVertex3f( 1, -1, -1);
369 glTexCoord2f(1, 1); glVertex3f( 1, -1, 1);
370 glTexCoord2f(0, 1); glVertex3f(-1, -1, 1);
373 glTexCoord2f(0, 0); glVertex3f(-1, 1, -1);
374 glTexCoord2f(1, 0); glVertex3f( 1, 1, -1);
375 glTexCoord2f(1, 1); glVertex3f( 1, 1, 1);
376 glTexCoord2f(0, 1); glVertex3f(-1, 1, 1);
379 glBindTexture(GL_TEXTURE_2D
, Textures
[2]);
381 glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
382 glTexCoord2f(1, 0); glVertex3f( 1, -1, -1);
383 glTexCoord2f(1, 1); glVertex3f( 1, 1, -1);
384 glTexCoord2f(0, 1); glVertex3f(-1, 1, -1);
387 glTexCoord2f(0, 0); glVertex3f(-1, -1, 1);
388 glTexCoord2f(1, 0); glVertex3f( 1, -1, 1);
389 glTexCoord2f(1, 1); glVertex3f( 1, 1, 1);
390 glTexCoord2f(0, 1); glVertex3f(-1, 1, 1);
397 if (!wglMakeCurrent(NULL
, NULL
)) {
398 Error("wglMakeCurrent failed in Redraw");
400 LeaveCriticalSection(&h
->drawMutex
);
404 threadRunner (void *arg
)
406 struct thread_init_arg
*tia
= (struct thread_init_arg
*) arg
;
408 PIXELFORMATDESCRIPTOR pfd
= {0};
411 win
= &Windows
[tia
->id
];
413 win
->hDC
= GetDC(win
->Win
);
415 Error("Couldn't obtain HDC");
418 /* Wait for the previous thread */
420 WaitForSingleObject(Windows
[tia
->id
- 1].hEventInitialised
, INFINITE
);
424 pfd
.dwFlags
= PFD_DOUBLEBUFFER
| PFD_DRAW_TO_WINDOW
| PFD_SUPPORT_OPENGL
;
425 pfd
.iLayerType
= PFD_MAIN_PLANE
;
426 pfd
.iPixelType
= PFD_TYPE_RGBA
;
427 pfd
.nSize
= sizeof(pfd
);
430 visinfo
= ChoosePixelFormat(win
->hDC
, &pfd
);
432 Error("Unable to find RGB, Z, double-buffered visual");
435 SetPixelFormat(win
->hDC
, visinfo
, &pfd
);
436 win
->Context
= wglCreateContext(win
->hDC
);
438 Error("Couldn't create WGL context");
441 if (win
->sharedContext
) {
442 if(!wglShareLists(win
->sharedContext
, win
->Context
))
443 Error("Couldn't share WGL context lists");
446 SetEvent(win
->hEventInitialised
);
448 /* Wait for all threads to initialize otherwise wglShareLists will fail */
449 if(tia
->id
< NumWindows
- 1)
450 WaitForSingleObject(Windows
[NumWindows
- 1].hEventInitialised
, INFINITE
);
452 SendMessage(win
->Win
, WM_SIZE
, 0, 0);
457 /* wait 1 ms for signal either to exit or process messages */
458 switch (MsgWaitForMultipleObjects(1, &terminate
, FALSE
, 1, QS_ALLINPUT
)) {
460 SendMessage(win
->Win
, WM_CLOSE
, 0, 0);
462 case WAIT_OBJECT_0
+ 1:
466 while (PeekMessage(&msg
, NULL
, 0, 0, PM_REMOVE
)) {
467 if (msg
.message
== WM_QUIT
) {
470 TranslateMessage(&msg
);
471 DispatchMessage(&msg
);
481 Resize(struct window
*h
, unsigned int width
, unsigned int height
)
486 EnterCriticalSection(&h
->drawMutex
);
488 if (!wglMakeCurrent(h
->hDC
, h
->Context
)) {
489 LeaveCriticalSection(&h
->drawMutex
);
490 Error("wglMakeCurrent failed in Resize()");
494 glViewport(0, 0, width
, height
);
495 glMatrixMode(GL_PROJECTION
);
497 glFrustum(-1, 1, -1, 1, 2, 10);
498 glMatrixMode(GL_MODELVIEW
);
500 glTranslatef(0, 0, -4.5);
501 if (!wglMakeCurrent(NULL
, NULL
)) {
502 Error("wglMakeCurrent failed in Resize()");
504 LeaveCriticalSection(&h
->drawMutex
);
508 main(int argc
, char *argv
[])
510 struct thread_init_arg tia
[MAX_WINDOWS
];
511 struct window
*h
[MAX_WINDOWS
];
512 HANDLE threads
[MAX_WINDOWS
];
515 terminate
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
517 if (initMainthread())
520 /* four windows and contexts sharing display lists and texture objects */
521 h
[0] = AddWindow( 10, 10, gCtx
);
522 h
[1] = AddWindow(330, 10, gCtx
);
523 h
[2] = AddWindow( 10, 350, gCtx
);
524 h
[3] = AddWindow(330, 350, gCtx
);
526 for (i
= 0; i
< NumWindows
; i
++) {
527 Windows
[i
].hEventInitialised
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
530 for (i
= 0; i
< NumWindows
; i
++) {
534 threads
[i
] = CreateThread(NULL
, 0, threadRunner
, &tia
[i
], 0, &id
);
536 WaitForSingleObject(Windows
[i
].hEventInitialised
, INFINITE
);
539 if (!wglMakeCurrent(gHDC
, gCtx
)) {
540 Error("wglMakeCurrent failed for init thread.");
549 /* wait 1 ms for signal either to exit or process messages */
550 switch (MsgWaitForMultipleObjects(NumWindows
, threads
, TRUE
, 1, QS_ALLINPUT
)) {
555 while (PeekMessage(&msg
, NULL
, 0, 0, PM_REMOVE
)) {
556 if (msg
.message
== WM_QUIT
) {
559 TranslateMessage(&msg
);
560 DispatchMessage(&msg
);