sharedtex_mt.c revision 7ec3b29a
1/* 2 * Test sharing of display lists and texture objects between GLX contests. 3 * Brian Paul 4 * Summer 2000 5 * 6 * 7 * Copyright (C) 2000 Brian Paul All Rights Reserved. 8 * 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: 15 * 16 * The above copyright notice and this permission notice shall be included 17 * in all copies or substantial portions of the Software. 18 * 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. 25 * 26 * 27 * Modified 2009 for multithreading by Thomas Hellstrom. 28 * 29 * Port to windows by Michal Krol. 30 */ 31 32 33#include <windows.h> 34#include <GL/gl.h> 35#include <stdio.h> 36#include <stdlib.h> 37#include <string.h> 38 39struct thread_init_arg { 40 int id; 41}; 42 43struct window { 44 CRITICAL_SECTION drawMutex; 45 HDC hDC; 46 HWND Win; 47 HGLRC Context; 48 float Angle; 49 int Id; 50 HGLRC sharedContext; 51 HANDLE hEventInitialised; 52}; 53 54 55#define MAX_WINDOWS 20 56static struct window Windows[MAX_WINDOWS]; 57static int NumWindows = 0; 58static HANDLE terminate = NULL; 59static HGLRC gCtx = NULL; 60static HDC gHDC = NULL; 61static GLuint Textures[3]; 62 63 64 65static void 66Error(const char *msg) 67{ 68 fprintf(stderr, "Error - %s\n", msg); 69 exit(1); 70} 71 72static void 73Resize(struct window *h, unsigned int width, unsigned int height); 74 75static LRESULT CALLBACK 76WndProc(HWND hWnd, 77 UINT uMsg, 78 WPARAM wParam, 79 LPARAM lParam ) 80{ 81 switch (uMsg) { 82 case WM_KEYDOWN: 83 SetEvent(terminate); 84 break; 85 case WM_SIZE: 86 { 87 LONG_PTR index = GetWindowLongPtr(hWnd, GWLP_USERDATA); 88 89 if (index >= 0 && index < MAX_WINDOWS) { 90 RECT r; 91 92 GetClientRect(hWnd, &r); 93 Resize(&Windows[index], r.right, r.bottom); 94 } 95 } 96 break; 97 case WM_CREATE: 98 { 99 CREATESTRUCT *pcs = (CREATESTRUCT *) lParam; 100 101 SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) pcs->lpCreateParams); 102 } 103 break; 104 case WM_DESTROY: 105 PostQuitMessage(0); 106 break; 107 default: 108 return DefWindowProc(hWnd, uMsg, wParam, lParam); 109 } 110 111 return 0; 112} 113 114static int 115initMainthread(void) 116{ 117 WNDCLASS wc = {0}; 118 HWND win; 119 PIXELFORMATDESCRIPTOR pfd; 120 int visinfo; 121 122 wc.lpfnWndProc = WndProc; 123 wc.lpszClassName = "sharedtex_mt.hidden"; 124 wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; 125 RegisterClass(&wc); 126 127 win = CreateWindowEx(0, 128 wc.lpszClassName, 129 "sharedtex_mt.hidden", 130 WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 131 CW_USEDEFAULT, 132 CW_USEDEFAULT, 133 CW_USEDEFAULT, 134 CW_USEDEFAULT, 135 NULL, 136 NULL, 137 wc.hInstance, 138 (LPVOID) -1); 139 if (!win) { 140 Error("Couldn't create window"); 141 } 142 143 gHDC = GetDC(win); 144 if (!gHDC) { 145 Error("Couldn't obtain HDC"); 146 } 147 148 memset(&pfd, 0, sizeof(pfd)); 149 pfd.cColorBits = 24; 150 pfd.cDepthBits = 24; 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); 155 pfd.nVersion = 1; 156 157 visinfo = ChoosePixelFormat(gHDC, &pfd); 158 if (!visinfo) { 159 Error("Unable to find RGB, Z, double-buffered visual"); 160 } 161 162 SetPixelFormat(gHDC, visinfo, &pfd); 163 gCtx = wglCreateContext(gHDC); 164 if (!gCtx) { 165 Error("Couldn't create WGL context"); 166 } 167 168 return 0; 169} 170 171static struct window * 172AddWindow(int xpos, int ypos, HGLRC sCtx) 173{ 174 struct window *win = &Windows[NumWindows]; 175 WNDCLASS wc = {0}; 176 int width = 300, height = 300; 177 178 if (NumWindows >= MAX_WINDOWS) 179 return NULL; 180 181 memset(win, 0, sizeof(*win)); 182 InitializeCriticalSection(&win->drawMutex); 183 win->Angle = 0.0; 184 win->Id = NumWindows++; 185 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; 192 RegisterClass(&wc); 193 194 win->Win = CreateWindowEx(0, 195 wc.lpszClassName, 196 "sharedtex_mt", 197 WS_SIZEBOX | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 198 xpos, 199 ypos, 200 width, 201 height, 202 NULL, 203 NULL, 204 wc.hInstance, 205 (LPVOID) win->Id); 206 if (!win->Win) { 207 Error("Couldn't create window"); 208 } 209 210 win->sharedContext = sCtx; 211 212 ShowWindow(win->Win, SW_SHOW); 213 214 return win; 215} 216 217 218static void 219InitGLstuff(void) 220{ 221 glGenTextures(3, Textures); 222 223 /* setup first texture object */ 224 { 225 GLubyte image[16][16][4]; 226 GLint i, j; 227 glBindTexture(GL_TEXTURE_2D, Textures[0]); 228 229 /* red/white checkerboard */ 230 for (i = 0; i < 16; i++) { 231 for (j = 0; j < 16; j++) { 232 if ((i ^ j) & 1) { 233 image[i][j][0] = 255; 234 image[i][j][1] = 255; 235 image[i][j][2] = 255; 236 image[i][j][3] = 255; 237 } 238 else { 239 image[i][j][0] = 255; 240 image[i][j][1] = 0; 241 image[i][j][2] = 0; 242 image[i][j][3] = 255; 243 } 244 } 245 } 246 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); 252 } 253 254 /* setup second texture object */ 255 { 256 GLubyte image[8][8][3]; 257 GLint i, j; 258 glBindTexture(GL_TEXTURE_2D, Textures[1]); 259 260 /* green/yellow checkerboard */ 261 for (i = 0; i < 8; i++) { 262 for (j = 0; j < 8; j++) { 263 if ((i ^ j) & 1) { 264 image[i][j][0] = 0; 265 image[i][j][1] = 255; 266 image[i][j][2] = 0; 267 } 268 else { 269 image[i][j][0] = 255; 270 image[i][j][1] = 255; 271 image[i][j][2] = 0; 272 } 273 } 274 } 275 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); 281 } 282 283 /* setup second texture object */ 284 { 285 GLubyte image[4][4][3]; 286 GLint i, j; 287 glBindTexture(GL_TEXTURE_2D, Textures[2]); 288 289 /* blue/gray checkerboard */ 290 for (i = 0; i < 4; i++) { 291 for (j = 0; j < 4; j++) { 292 if ((i ^ j) & 1) { 293 image[i][j][0] = 0; 294 image[i][j][1] = 0; 295 image[i][j][2] = 255; 296 } 297 else { 298 image[i][j][0] = 200; 299 image[i][j][1] = 200; 300 image[i][j][2] = 200; 301 } 302 } 303 } 304 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); 310 } 311 312 /* Now make the cube object display list */ 313 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)); 317} 318 319static void 320Redraw(struct window *h) 321{ 322 EnterCriticalSection(&h->drawMutex); 323 if (!wglMakeCurrent(h->hDC, h->Context)) { 324 LeaveCriticalSection(&h->drawMutex); 325 Error("wglMakeCurrent failed in Redraw"); 326 return; 327 } 328 329 h->Angle += 1.0; 330 331 glShadeModel(GL_FLAT); 332 glClearColor(0.25, 0.25, 0.25, 1.0); 333 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 334 335 glEnable(GL_TEXTURE_2D); 336 glEnable(GL_DEPTH_TEST); 337 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 338 339 glColor3f(1, 1, 1); 340 341 glPushMatrix(); 342 if (h->Id == 0) 343 glRotatef(h->Angle, 0, 1, -1); 344 else if (h->Id == 1) 345 glRotatef(-(h->Angle), 0, 1, -1); 346 else if (h->Id == 2) 347 glRotatef(h->Angle, 0, 1, 1); 348 else if (h->Id == 3) 349 glRotatef(-(h->Angle), 0, 1, 1); 350 glBindTexture(GL_TEXTURE_2D, Textures[0]); 351 glBegin(GL_POLYGON); 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); 356 glEnd(); 357 glBegin(GL_POLYGON); 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); 362 glEnd(); 363 364 glBindTexture(GL_TEXTURE_2D, Textures[1]); 365 glBegin(GL_POLYGON); 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); 370 glEnd(); 371 glBegin(GL_POLYGON); 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); 376 glEnd(); 377 378 glBindTexture(GL_TEXTURE_2D, Textures[2]); 379 glBegin(GL_POLYGON); 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); 384 glEnd(); 385 glBegin(GL_POLYGON); 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); 390 glEnd(); 391 392 glPopMatrix(); 393 394 SwapBuffers(h->hDC); 395 396 if (!wglMakeCurrent(NULL, NULL)) { 397 Error("wglMakeCurrent failed in Redraw"); 398 } 399 LeaveCriticalSection(&h->drawMutex); 400} 401 402static DWORD WINAPI 403threadRunner (void *arg) 404{ 405 struct thread_init_arg *tia = (struct thread_init_arg *) arg; 406 struct window *win; 407 PIXELFORMATDESCRIPTOR pfd; 408 int visinfo; 409 410 win = &Windows[tia->id]; 411 412 win->hDC = GetDC(win->Win); 413 if (!win->hDC) { 414 Error("Couldn't obtain HDC"); 415 } 416 417 /* Wait for the previous thread */ 418 if(tia->id > 0) 419 WaitForSingleObject(Windows[tia->id - 1].hEventInitialised, INFINITE); 420 421 memset(&pfd, 0, sizeof(pfd)); 422 pfd.cColorBits = 24; 423 pfd.cDepthBits = 24; 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); 428 pfd.nVersion = 1; 429 430 visinfo = ChoosePixelFormat(win->hDC, &pfd); 431 if (!visinfo) { 432 Error("Unable to find RGB, Z, double-buffered visual"); 433 } 434 435 SetPixelFormat(win->hDC, visinfo, &pfd); 436 win->Context = wglCreateContext(win->hDC); 437 if (!win->Context) { 438 Error("Couldn't create WGL context"); 439 } 440 441 if (win->sharedContext) { 442 if(!wglShareLists(win->sharedContext, win->Context)) 443 Error("Couldn't share WGL context lists"); 444 } 445 446 SetEvent(win->hEventInitialised); 447 448 /* Wait for all threads to initialize otherwise wglShareLists will fail */ 449 if(tia->id < NumWindows - 1) 450 WaitForSingleObject(Windows[NumWindows - 1].hEventInitialised, INFINITE); 451 452 SendMessage(win->Win, WM_SIZE, 0, 0); 453 454 while (1) { 455 MSG msg; 456 457 /* wait 1 ms for signal either to exit or process messages */ 458 switch (MsgWaitForMultipleObjects(1, &terminate, FALSE, 1, QS_ALLINPUT)) { 459 case WAIT_OBJECT_0: 460 SendMessage(win->Win, WM_CLOSE, 0, 0); 461 break; 462 case WAIT_OBJECT_0 + 1: 463 break; 464 } 465 466 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { 467 if (msg.message == WM_QUIT) { 468 return 0; 469 } 470 TranslateMessage(&msg); 471 DispatchMessage(&msg); 472 } 473 474 Redraw(win); 475 } 476 477 return 0; 478} 479 480static void 481Resize(struct window *h, unsigned int width, unsigned int height) 482{ 483 if (!h->Context) 484 return; 485 486 EnterCriticalSection(&h->drawMutex); 487 488 if (!wglMakeCurrent(h->hDC, h->Context)) { 489 LeaveCriticalSection(&h->drawMutex); 490 Error("wglMakeCurrent failed in Resize()"); 491 return; 492 } 493 494 glViewport(0, 0, width, height); 495 glMatrixMode(GL_PROJECTION); 496 glLoadIdentity(); 497 glFrustum(-1, 1, -1, 1, 2, 10); 498 glMatrixMode(GL_MODELVIEW); 499 glLoadIdentity(); 500 glTranslatef(0, 0, -4.5); 501 if (!wglMakeCurrent(NULL, NULL)) { 502 Error("wglMakeCurrent failed in Resize()"); 503 } 504 LeaveCriticalSection(&h->drawMutex); 505} 506 507int 508main(int argc, char *argv[]) 509{ 510 struct thread_init_arg tia[MAX_WINDOWS]; 511 HANDLE threads[MAX_WINDOWS]; 512 int i; 513 514 terminate = CreateEvent(NULL, TRUE, FALSE, NULL); 515 516 if (initMainthread()) 517 return -1; 518 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); 524 525 for (i = 0; i < NumWindows; i++) { 526 Windows[i].hEventInitialised = CreateEvent(NULL, TRUE, FALSE, NULL); 527 } 528 529 for (i = 0; i < NumWindows; i++) { 530 DWORD id; 531 532 tia[i].id = i; 533 threads[i] = CreateThread(NULL, 0, threadRunner, &tia[i], 0, &id); 534 535 WaitForSingleObject(Windows[i].hEventInitialised, INFINITE); 536 } 537 538 if (!wglMakeCurrent(gHDC, gCtx)) { 539 Error("wglMakeCurrent failed for init thread."); 540 return -1; 541 } 542 543 InitGLstuff(); 544 545 while (1) { 546 MSG msg; 547 548 /* wait 1 ms for signal either to exit or process messages */ 549 switch (MsgWaitForMultipleObjects(NumWindows, threads, TRUE, 1, QS_ALLINPUT)) { 550 case WAIT_OBJECT_0: 551 return 0; 552 } 553 554 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { 555 if (msg.message == WM_QUIT) { 556 return 0; 557 } 558 TranslateMessage(&msg); 559 DispatchMessage(&msg); 560 } 561 } 562 563 return 0; 564} 565