sharedtex_mt.c revision 32001f49
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 39#pragma comment(lib, "opengl32.lib") 40 41struct thread_init_arg { 42 int id; 43}; 44 45struct window { 46 CRITICAL_SECTION drawMutex; 47 HDC hDC; 48 HWND Win; 49 HGLRC Context; 50 float Angle; 51 int Id; 52 HGLRC sharedContext; 53 HANDLE hEventInitialised; 54}; 55 56 57#define MAX_WINDOWS 20 58static struct window Windows[MAX_WINDOWS]; 59static int NumWindows = 0; 60static HANDLE terminate = NULL; 61static HGLRC gCtx = NULL; 62static HDC gHDC = NULL; 63static GLuint Textures[3]; 64 65 66 67static void 68Error(const char *msg) 69{ 70 fprintf(stderr, "Error - %s\n", msg); 71 exit(1); 72} 73 74static void 75Resize(struct window *h, unsigned int width, unsigned int height); 76 77static LRESULT CALLBACK 78WndProc(HWND hWnd, 79 UINT uMsg, 80 WPARAM wParam, 81 LPARAM lParam ) 82{ 83 switch (uMsg) { 84 case WM_KEYDOWN: 85 SetEvent(terminate); 86 break; 87 case WM_SIZE: 88 { 89 LONG_PTR index = GetWindowLongPtr(hWnd, GWLP_USERDATA); 90 91 if (index >= 0 && index < MAX_WINDOWS) { 92 RECT r; 93 94 GetClientRect(hWnd, &r); 95 Resize(&Windows[index], r.right, r.bottom); 96 } 97 } 98 break; 99 case WM_CREATE: 100 { 101 CREATESTRUCT *pcs = (CREATESTRUCT *) lParam; 102 103 SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) pcs->lpCreateParams); 104 } 105 break; 106 case WM_DESTROY: 107 PostQuitMessage(0); 108 break; 109 default: 110 return DefWindowProc(hWnd, uMsg, wParam, lParam); 111 } 112 113 return 0; 114} 115 116static int 117initMainthread(void) 118{ 119 WNDCLASS wc = {0}; 120 HWND win; 121 PIXELFORMATDESCRIPTOR pfd = {0}; 122 int visinfo; 123 124 wc.lpfnWndProc = WndProc; 125 wc.lpszClassName = "sharedtex_mt.hidden"; 126 wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; 127 RegisterClass(&wc); 128 129 win = CreateWindowEx(0, 130 wc.lpszClassName, 131 "sharedtex_mt.hidden", 132 WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 133 CW_USEDEFAULT, 134 CW_USEDEFAULT, 135 CW_USEDEFAULT, 136 CW_USEDEFAULT, 137 NULL, 138 NULL, 139 wc.hInstance, 140 (LPVOID) -1); 141 if (!win) { 142 Error("Couldn't create window"); 143 } 144 145 gHDC = GetDC(win); 146 if (!gHDC) { 147 Error("Couldn't obtain HDC"); 148 } 149 150 pfd.cColorBits = 24; 151 pfd.cDepthBits = 24; 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); 156 pfd.nVersion = 1; 157 158 visinfo = ChoosePixelFormat(gHDC, &pfd); 159 if (!visinfo) { 160 Error("Unable to find RGB, Z, double-buffered visual"); 161 } 162 163 SetPixelFormat(gHDC, visinfo, &pfd); 164 gCtx = wglCreateContext(gHDC); 165 if (!gCtx) { 166 Error("Couldn't create WGL context"); 167 } 168 169 return 0; 170} 171 172static struct window * 173AddWindow(int xpos, int ypos, HGLRC sCtx) 174{ 175 struct window *win = &Windows[NumWindows]; 176 WNDCLASS wc = {0}; 177 int width = 300, height = 300; 178 179 if (NumWindows >= MAX_WINDOWS) 180 return NULL; 181 182 memset(win, 0, sizeof(*win)); 183 InitializeCriticalSection(&win->drawMutex); 184 win->Angle = 0.0; 185 win->Id = NumWindows++; 186 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; 193 RegisterClass(&wc); 194 195 win->Win = CreateWindowEx(0, 196 wc.lpszClassName, 197 "sharedtex_mt", 198 WS_SIZEBOX | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 199 xpos, 200 ypos, 201 width, 202 height, 203 NULL, 204 NULL, 205 wc.hInstance, 206 (LPVOID) win->Id); 207 if (!win->Win) { 208 Error("Couldn't create window"); 209 } 210 211 win->sharedContext = sCtx; 212 213 ShowWindow(win->Win, SW_SHOW); 214 215 return win; 216} 217 218 219static void 220InitGLstuff(void) 221{ 222 glGenTextures(3, Textures); 223 224 /* setup first texture object */ 225 { 226 GLubyte image[16][16][4]; 227 GLint i, j; 228 glBindTexture(GL_TEXTURE_2D, Textures[0]); 229 230 /* red/white checkerboard */ 231 for (i = 0; i < 16; i++) { 232 for (j = 0; j < 16; j++) { 233 if ((i ^ j) & 1) { 234 image[i][j][0] = 255; 235 image[i][j][1] = 255; 236 image[i][j][2] = 255; 237 image[i][j][3] = 255; 238 } 239 else { 240 image[i][j][0] = 255; 241 image[i][j][1] = 0; 242 image[i][j][2] = 0; 243 image[i][j][3] = 255; 244 } 245 } 246 } 247 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); 253 } 254 255 /* setup second texture object */ 256 { 257 GLubyte image[8][8][3]; 258 GLint i, j; 259 glBindTexture(GL_TEXTURE_2D, Textures[1]); 260 261 /* green/yellow checkerboard */ 262 for (i = 0; i < 8; i++) { 263 for (j = 0; j < 8; j++) { 264 if ((i ^ j) & 1) { 265 image[i][j][0] = 0; 266 image[i][j][1] = 255; 267 image[i][j][2] = 0; 268 } 269 else { 270 image[i][j][0] = 255; 271 image[i][j][1] = 255; 272 image[i][j][2] = 0; 273 } 274 } 275 } 276 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); 282 } 283 284 /* setup second texture object */ 285 { 286 GLubyte image[4][4][3]; 287 GLint i, j; 288 glBindTexture(GL_TEXTURE_2D, Textures[2]); 289 290 /* blue/gray checkerboard */ 291 for (i = 0; i < 4; i++) { 292 for (j = 0; j < 4; j++) { 293 if ((i ^ j) & 1) { 294 image[i][j][0] = 0; 295 image[i][j][1] = 0; 296 image[i][j][2] = 255; 297 } 298 else { 299 image[i][j][0] = 200; 300 image[i][j][1] = 200; 301 image[i][j][2] = 200; 302 } 303 } 304 } 305 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); 311 } 312 313 /* Now make the cube object display list */ 314 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)); 318} 319 320static void 321Redraw(struct window *h) 322{ 323 EnterCriticalSection(&h->drawMutex); 324 if (!wglMakeCurrent(h->hDC, h->Context)) { 325 LeaveCriticalSection(&h->drawMutex); 326 Error("wglMakeCurrent failed in Redraw"); 327 return; 328 } 329 330 h->Angle += 1.0; 331 332 glShadeModel(GL_FLAT); 333 glClearColor(0.25, 0.25, 0.25, 1.0); 334 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 335 336 glEnable(GL_TEXTURE_2D); 337 glEnable(GL_DEPTH_TEST); 338 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 339 340 glColor3f(1, 1, 1); 341 342 glPushMatrix(); 343 if (h->Id == 0) 344 glRotatef(h->Angle, 0, 1, -1); 345 else if (h->Id == 1) 346 glRotatef(-(h->Angle), 0, 1, -1); 347 else if (h->Id == 2) 348 glRotatef(h->Angle, 0, 1, 1); 349 else if (h->Id == 3) 350 glRotatef(-(h->Angle), 0, 1, 1); 351 glBindTexture(GL_TEXTURE_2D, Textures[0]); 352 glBegin(GL_POLYGON); 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); 357 glEnd(); 358 glBegin(GL_POLYGON); 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); 363 glEnd(); 364 365 glBindTexture(GL_TEXTURE_2D, Textures[1]); 366 glBegin(GL_POLYGON); 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); 371 glEnd(); 372 glBegin(GL_POLYGON); 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); 377 glEnd(); 378 379 glBindTexture(GL_TEXTURE_2D, Textures[2]); 380 glBegin(GL_POLYGON); 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); 385 glEnd(); 386 glBegin(GL_POLYGON); 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); 391 glEnd(); 392 393 glPopMatrix(); 394 395 SwapBuffers(h->hDC); 396 397 if (!wglMakeCurrent(NULL, NULL)) { 398 Error("wglMakeCurrent failed in Redraw"); 399 } 400 LeaveCriticalSection(&h->drawMutex); 401} 402 403static DWORD WINAPI 404threadRunner (void *arg) 405{ 406 struct thread_init_arg *tia = (struct thread_init_arg *) arg; 407 struct window *win; 408 PIXELFORMATDESCRIPTOR pfd = {0}; 409 int visinfo; 410 411 win = &Windows[tia->id]; 412 413 win->hDC = GetDC(win->Win); 414 if (!win->hDC) { 415 Error("Couldn't obtain HDC"); 416 } 417 418 /* Wait for the previous thread */ 419 if(tia->id > 0) 420 WaitForSingleObject(Windows[tia->id - 1].hEventInitialised, INFINITE); 421 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 struct window *h[MAX_WINDOWS]; 512 HANDLE threads[MAX_WINDOWS]; 513 int i; 514 515 terminate = CreateEvent(NULL, TRUE, FALSE, NULL); 516 517 if (initMainthread()) 518 return -1; 519 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); 525 526 for (i = 0; i < NumWindows; i++) { 527 Windows[i].hEventInitialised = CreateEvent(NULL, TRUE, FALSE, NULL); 528 } 529 530 for (i = 0; i < NumWindows; i++) { 531 DWORD id; 532 533 tia[i].id = i; 534 threads[i] = CreateThread(NULL, 0, threadRunner, &tia[i], 0, &id); 535 536 WaitForSingleObject(Windows[i].hEventInitialised, INFINITE); 537 } 538 539 if (!wglMakeCurrent(gHDC, gCtx)) { 540 Error("wglMakeCurrent failed for init thread."); 541 return -1; 542 } 543 544 InitGLstuff(); 545 546 while (1) { 547 MSG msg; 548 549 /* wait 1 ms for signal either to exit or process messages */ 550 switch (MsgWaitForMultipleObjects(NumWindows, threads, TRUE, 1, QS_ALLINPUT)) { 551 case WAIT_OBJECT_0: 552 return 0; 553 } 554 555 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { 556 if (msg.message == WM_QUIT) { 557 return 0; 558 } 559 TranslateMessage(&msg); 560 DispatchMessage(&msg); 561 } 562 } 563 564 return 0; 565} 566