wglgears: add srgb-mode to usage
[mesa-demos.git] / src / wgl / sharedtex_mt.c
blob084b00f48bfa8ece57774cace71fe65711ca7701
1 /*
2 * Test sharing of display lists and texture objects between GLX contests.
3 * Brian Paul
4 * Summer 2000
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.
33 #include <windows.h>
34 #include <GL/gl.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
39 struct thread_init_arg {
40 int id;
43 struct 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;
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];
65 static void
66 Error(const char *msg)
68 fprintf(stderr, "Error - %s\n", msg);
69 exit(1);
72 static void
73 Resize(struct window *h, unsigned int width, unsigned int height);
75 static LRESULT CALLBACK
76 WndProc(HWND hWnd,
77 UINT uMsg,
78 WPARAM wParam,
79 LPARAM lParam )
81 switch (uMsg) {
82 case WM_KEYDOWN:
83 SetEvent(terminate);
84 break;
85 case WM_SIZE:
87 LONG_PTR index = GetWindowLongPtr(hWnd, GWLP_USERDATA);
89 if (index >= 0 && index < MAX_WINDOWS) {
90 RECT r;
92 GetClientRect(hWnd, &r);
93 Resize(&Windows[index], r.right, r.bottom);
96 break;
97 case WM_CREATE:
99 CREATESTRUCT *pcs = (CREATESTRUCT *) lParam;
101 SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) pcs->lpCreateParams);
103 break;
104 case WM_DESTROY:
105 PostQuitMessage(0);
106 break;
107 default:
108 return DefWindowProc(hWnd, uMsg, wParam, lParam);
111 return 0;
114 static int
115 initMainthread(void)
117 WNDCLASS wc = {0};
118 HWND win;
119 PIXELFORMATDESCRIPTOR pfd;
120 int visinfo;
122 wc.lpfnWndProc = WndProc;
123 wc.lpszClassName = "sharedtex_mt.hidden";
124 wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
125 RegisterClass(&wc);
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");
143 gHDC = GetDC(win);
144 if (!gHDC) {
145 Error("Couldn't obtain HDC");
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;
157 visinfo = ChoosePixelFormat(gHDC, &pfd);
158 if (!visinfo) {
159 Error("Unable to find RGB, Z, double-buffered visual");
162 SetPixelFormat(gHDC, visinfo, &pfd);
163 gCtx = wglCreateContext(gHDC);
164 if (!gCtx) {
165 Error("Couldn't create WGL context");
168 return 0;
171 static struct window *
172 AddWindow(int xpos, int ypos, HGLRC sCtx)
174 struct window *win = &Windows[NumWindows];
175 WNDCLASS wc = {0};
176 int width = 300, height = 300;
178 if (NumWindows >= MAX_WINDOWS)
179 return NULL;
181 memset(win, 0, sizeof(*win));
182 InitializeCriticalSection(&win->drawMutex);
183 win->Angle = 0.0;
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;
192 RegisterClass(&wc);
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");
210 win->sharedContext = sCtx;
212 ShowWindow(win->Win, SW_SHOW);
214 return win;
218 static void
219 InitGLstuff(void)
221 glGenTextures(3, Textures);
223 /* setup first texture object */
225 GLubyte image[16][16][4];
226 GLint i, j;
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++) {
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;
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;
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];
257 GLint i, j;
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++) {
263 if ((i ^ j) & 1) {
264 image[i][j][0] = 0;
265 image[i][j][1] = 255;
266 image[i][j][2] = 0;
268 else {
269 image[i][j][0] = 255;
270 image[i][j][1] = 255;
271 image[i][j][2] = 0;
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];
286 GLint i, j;
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++) {
292 if ((i ^ j) & 1) {
293 image[i][j][0] = 0;
294 image[i][j][1] = 0;
295 image[i][j][2] = 255;
297 else {
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));
319 static void
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");
326 return;
329 h->Angle += 1.0;
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);
339 glColor3f(1, 1, 1);
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();
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();
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();
392 glPopMatrix();
394 SwapBuffers(h->hDC);
396 if (!wglMakeCurrent(NULL, NULL)) {
397 Error("wglMakeCurrent failed in Redraw");
399 LeaveCriticalSection(&h->drawMutex);
402 static DWORD WINAPI
403 threadRunner (void *arg)
405 struct thread_init_arg *tia = (struct thread_init_arg *) arg;
406 struct window *win;
407 PIXELFORMATDESCRIPTOR pfd;
408 int visinfo;
410 win = &Windows[tia->id];
412 win->hDC = GetDC(win->Win);
413 if (!win->hDC) {
414 Error("Couldn't obtain HDC");
417 /* Wait for the previous thread */
418 if(tia->id > 0)
419 WaitForSingleObject(Windows[tia->id - 1].hEventInitialised, INFINITE);
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;
430 visinfo = ChoosePixelFormat(win->hDC, &pfd);
431 if (!visinfo) {
432 Error("Unable to find RGB, Z, double-buffered visual");
435 SetPixelFormat(win->hDC, visinfo, &pfd);
436 win->Context = wglCreateContext(win->hDC);
437 if (!win->Context) {
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);
454 while (1) {
455 MSG msg;
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;
466 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
467 if (msg.message == WM_QUIT) {
468 return 0;
470 TranslateMessage(&msg);
471 DispatchMessage(&msg);
474 Redraw(win);
477 return 0;
480 static void
481 Resize(struct window *h, unsigned int width, unsigned int height)
483 if (!h->Context)
484 return;
486 EnterCriticalSection(&h->drawMutex);
488 if (!wglMakeCurrent(h->hDC, h->Context)) {
489 LeaveCriticalSection(&h->drawMutex);
490 Error("wglMakeCurrent failed in Resize()");
491 return;
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()");
504 LeaveCriticalSection(&h->drawMutex);
508 main(int argc, char *argv[])
510 struct thread_init_arg tia[MAX_WINDOWS];
511 HANDLE threads[MAX_WINDOWS];
512 int i;
514 terminate = CreateEvent(NULL, TRUE, FALSE, NULL);
516 if (initMainthread())
517 return -1;
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++) {
530 DWORD id;
532 tia[i].id = 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.");
540 return -1;
543 InitGLstuff();
545 while (1) {
546 MSG msg;
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;
554 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
555 if (msg.message == WM_QUIT) {
556 return 0;
558 TranslateMessage(&msg);
559 DispatchMessage(&msg);
563 return 0;