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 struct thread_init_arg
{
44 CRITICAL_SECTION drawMutex
;
51 HANDLE hEventInitialised
;
55 #define MAX_WINDOWS 20
56 static struct window Windows
[MAX_WINDOWS
];
57 static int NumWindows
= 0;
58 static HANDLE terminate
= NULL
;
59 static HGLRC gCtx
= NULL
;
60 static HDC gHDC
= NULL
;
61 static GLuint Textures
[3];
66 Error(const char *msg
)
68 fprintf(stderr
, "Error - %s\n", msg
);
73 Resize(struct window
*h
, unsigned int width
, unsigned int height
);
75 static LRESULT CALLBACK
87 LONG_PTR index
= GetWindowLongPtr(hWnd
, GWLP_USERDATA
);
89 if (index
>= 0 && index
< MAX_WINDOWS
) {
92 GetClientRect(hWnd
, &r
);
93 Resize(&Windows
[index
], r
.right
, r
.bottom
);
99 CREATESTRUCT
*pcs
= (CREATESTRUCT
*) lParam
;
101 SetWindowLongPtr(hWnd
, GWLP_USERDATA
, (LONG_PTR
) pcs
->lpCreateParams
);
108 return DefWindowProc(hWnd
, uMsg
, wParam
, lParam
);
119 PIXELFORMATDESCRIPTOR pfd
;
122 wc
.lpfnWndProc
= WndProc
;
123 wc
.lpszClassName
= "sharedtex_mt.hidden";
124 wc
.style
= CS_OWNDC
| CS_HREDRAW
| CS_VREDRAW
;
127 win
= CreateWindowEx(0,
129 "sharedtex_mt.hidden",
130 WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
,
140 Error("Couldn't create window");
145 Error("Couldn't obtain HDC");
148 memset(&pfd
, 0, sizeof(pfd
));
151 pfd
.dwFlags
= PFD_DOUBLEBUFFER
| PFD_DRAW_TO_WINDOW
| PFD_SUPPORT_OPENGL
;
152 pfd
.iLayerType
= PFD_MAIN_PLANE
;
153 pfd
.iPixelType
= PFD_TYPE_RGBA
;
154 pfd
.nSize
= sizeof(pfd
);
157 visinfo
= ChoosePixelFormat(gHDC
, &pfd
);
159 Error("Unable to find RGB, Z, double-buffered visual");
162 SetPixelFormat(gHDC
, visinfo
, &pfd
);
163 gCtx
= wglCreateContext(gHDC
);
165 Error("Couldn't create WGL context");
171 static struct window
*
172 AddWindow(int xpos
, int ypos
, HGLRC sCtx
)
174 struct window
*win
= &Windows
[NumWindows
];
176 int width
= 300, height
= 300;
178 if (NumWindows
>= MAX_WINDOWS
)
181 memset(win
, 0, sizeof(*win
));
182 InitializeCriticalSection(&win
->drawMutex
);
184 win
->Id
= NumWindows
++;
186 wc
.hbrBackground
= (HBRUSH
) (COLOR_BTNFACE
+ 1);
187 wc
.hCursor
= LoadCursor(NULL
, IDC_ARROW
);
188 wc
.hIcon
= LoadIcon(NULL
, IDI_APPLICATION
);
189 wc
.lpfnWndProc
= WndProc
;
190 wc
.lpszClassName
= "sharedtex_mt";
191 wc
.style
= CS_OWNDC
| CS_HREDRAW
| CS_VREDRAW
;
194 win
->Win
= CreateWindowEx(0,
197 WS_SIZEBOX
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
,
207 Error("Couldn't create window");
210 win
->sharedContext
= sCtx
;
212 ShowWindow(win
->Win
, SW_SHOW
);
221 glGenTextures(3, Textures
);
223 /* setup first texture object */
225 GLubyte image
[16][16][4];
227 glBindTexture(GL_TEXTURE_2D
, Textures
[0]);
229 /* red/white checkerboard */
230 for (i
= 0; i
< 16; i
++) {
231 for (j
= 0; j
< 16; j
++) {
233 image
[i
][j
][0] = 255;
234 image
[i
][j
][1] = 255;
235 image
[i
][j
][2] = 255;
236 image
[i
][j
][3] = 255;
239 image
[i
][j
][0] = 255;
242 image
[i
][j
][3] = 255;
247 glPixelStorei(GL_UNPACK_ALIGNMENT
, 1);
248 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, 16, 16, 0, GL_RGBA
,
249 GL_UNSIGNED_BYTE
, image
);
250 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
251 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
254 /* setup second texture object */
256 GLubyte image
[8][8][3];
258 glBindTexture(GL_TEXTURE_2D
, Textures
[1]);
260 /* green/yellow checkerboard */
261 for (i
= 0; i
< 8; i
++) {
262 for (j
= 0; j
< 8; j
++) {
265 image
[i
][j
][1] = 255;
269 image
[i
][j
][0] = 255;
270 image
[i
][j
][1] = 255;
276 glPixelStorei(GL_UNPACK_ALIGNMENT
, 2);
277 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGB
, 8, 8, 0, GL_RGB
,
278 GL_UNSIGNED_BYTE
, image
);
279 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
280 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
283 /* setup second texture object */
285 GLubyte image
[4][4][3];
287 glBindTexture(GL_TEXTURE_2D
, Textures
[2]);
289 /* blue/gray checkerboard */
290 for (i
= 0; i
< 4; i
++) {
291 for (j
= 0; j
< 4; j
++) {
295 image
[i
][j
][2] = 255;
298 image
[i
][j
][0] = 200;
299 image
[i
][j
][1] = 200;
300 image
[i
][j
][2] = 200;
305 glPixelStorei(GL_UNPACK_ALIGNMENT
, 2);
306 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGB
, 4, 4, 0, GL_RGB
,
307 GL_UNSIGNED_BYTE
, image
);
308 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
309 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
312 /* Now make the cube object display list */
314 printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER
));
315 printf("GL_VERSION: %s\n", (char *) glGetString(GL_VERSION
));
316 printf("GL_VENDOR: %s\n", (char *) glGetString(GL_VENDOR
));
320 Redraw(struct window
*h
)
322 EnterCriticalSection(&h
->drawMutex
);
323 if (!wglMakeCurrent(h
->hDC
, h
->Context
)) {
324 LeaveCriticalSection(&h
->drawMutex
);
325 Error("wglMakeCurrent failed in Redraw");
331 glShadeModel(GL_FLAT
);
332 glClearColor(0.25, 0.25, 0.25, 1.0);
333 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
335 glEnable(GL_TEXTURE_2D
);
336 glEnable(GL_DEPTH_TEST
);
337 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_REPLACE
);
343 glRotatef(h
->Angle
, 0, 1, -1);
345 glRotatef(-(h
->Angle
), 0, 1, -1);
347 glRotatef(h
->Angle
, 0, 1, 1);
349 glRotatef(-(h
->Angle
), 0, 1, 1);
350 glBindTexture(GL_TEXTURE_2D
, Textures
[0]);
352 glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
353 glTexCoord2f(1, 0); glVertex3f(-1, 1, -1);
354 glTexCoord2f(1, 1); glVertex3f(-1, 1, 1);
355 glTexCoord2f(0, 1); glVertex3f(-1, -1, 1);
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 glBindTexture(GL_TEXTURE_2D
, Textures
[1]);
366 glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
367 glTexCoord2f(1, 0); glVertex3f( 1, -1, -1);
368 glTexCoord2f(1, 1); glVertex3f( 1, -1, 1);
369 glTexCoord2f(0, 1); glVertex3f(-1, -1, 1);
372 glTexCoord2f(0, 0); glVertex3f(-1, 1, -1);
373 glTexCoord2f(1, 0); glVertex3f( 1, 1, -1);
374 glTexCoord2f(1, 1); glVertex3f( 1, 1, 1);
375 glTexCoord2f(0, 1); glVertex3f(-1, 1, 1);
378 glBindTexture(GL_TEXTURE_2D
, Textures
[2]);
380 glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
381 glTexCoord2f(1, 0); glVertex3f( 1, -1, -1);
382 glTexCoord2f(1, 1); glVertex3f( 1, 1, -1);
383 glTexCoord2f(0, 1); glVertex3f(-1, 1, -1);
386 glTexCoord2f(0, 0); glVertex3f(-1, -1, 1);
387 glTexCoord2f(1, 0); glVertex3f( 1, -1, 1);
388 glTexCoord2f(1, 1); glVertex3f( 1, 1, 1);
389 glTexCoord2f(0, 1); glVertex3f(-1, 1, 1);
396 if (!wglMakeCurrent(NULL
, NULL
)) {
397 Error("wglMakeCurrent failed in Redraw");
399 LeaveCriticalSection(&h
->drawMutex
);
403 threadRunner (void *arg
)
405 struct thread_init_arg
*tia
= (struct thread_init_arg
*) arg
;
407 PIXELFORMATDESCRIPTOR pfd
;
410 win
= &Windows
[tia
->id
];
412 win
->hDC
= GetDC(win
->Win
);
414 Error("Couldn't obtain HDC");
417 /* Wait for the previous thread */
419 WaitForSingleObject(Windows
[tia
->id
- 1].hEventInitialised
, INFINITE
);
421 memset(&pfd
, 0, sizeof(pfd
));
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 HANDLE threads
[MAX_WINDOWS
];
514 terminate
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
516 if (initMainthread())
519 /* four windows and contexts sharing display lists and texture objects */
520 AddWindow( 10, 10, gCtx
);
521 AddWindow(330, 10, gCtx
);
522 AddWindow( 10, 350, gCtx
);
523 AddWindow(330, 350, gCtx
);
525 for (i
= 0; i
< NumWindows
; i
++) {
526 Windows
[i
].hEventInitialised
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
529 for (i
= 0; i
< NumWindows
; i
++) {
533 threads
[i
] = CreateThread(NULL
, 0, threadRunner
, &tia
[i
], 0, &id
);
535 WaitForSingleObject(Windows
[i
].hEventInitialised
, INFINITE
);
538 if (!wglMakeCurrent(gHDC
, gCtx
)) {
539 Error("wglMakeCurrent failed for init thread.");
548 /* wait 1 ms for signal either to exit or process messages */
549 switch (MsgWaitForMultipleObjects(NumWindows
, threads
, TRUE
, 1, QS_ALLINPUT
)) {
554 while (PeekMessage(&msg
, NULL
, 0, 0, PM_REMOVE
)) {
555 if (msg
.message
== WM_QUIT
) {
558 TranslateMessage(&msg
);
559 DispatchMessage(&msg
);