demos: add missing binaries to .gitignore
[mesa-demos.git] / src / wgl / sharedtex_mt.c
blob161b2bba570a1d76b6f2d728012a9e22f0c7c560
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 #pragma comment(lib, "opengl32.lib")
41 struct thread_init_arg {
42 int id;
45 struct 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;
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];
67 static void
68 Error(const char *msg)
70 fprintf(stderr, "Error - %s\n", msg);
71 exit(1);
74 static void
75 Resize(struct window *h, unsigned int width, unsigned int height);
77 static LRESULT CALLBACK
78 WndProc(HWND hWnd,
79 UINT uMsg,
80 WPARAM wParam,
81 LPARAM lParam )
83 switch (uMsg) {
84 case WM_KEYDOWN:
85 SetEvent(terminate);
86 break;
87 case WM_SIZE:
89 LONG_PTR index = GetWindowLongPtr(hWnd, GWLP_USERDATA);
91 if (index >= 0 && index < MAX_WINDOWS) {
92 RECT r;
94 GetClientRect(hWnd, &r);
95 Resize(&Windows[index], r.right, r.bottom);
98 break;
99 case WM_CREATE:
101 CREATESTRUCT *pcs = (CREATESTRUCT *) lParam;
103 SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) pcs->lpCreateParams);
105 break;
106 case WM_DESTROY:
107 PostQuitMessage(0);
108 break;
109 default:
110 return DefWindowProc(hWnd, uMsg, wParam, lParam);
113 return 0;
116 static int
117 initMainthread(void)
119 WNDCLASS wc = {0};
120 HWND win;
121 PIXELFORMATDESCRIPTOR pfd = {0};
122 int visinfo;
124 wc.lpfnWndProc = WndProc;
125 wc.lpszClassName = "sharedtex_mt.hidden";
126 wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
127 RegisterClass(&wc);
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");
145 gHDC = GetDC(win);
146 if (!gHDC) {
147 Error("Couldn't obtain HDC");
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;
158 visinfo = ChoosePixelFormat(gHDC, &pfd);
159 if (!visinfo) {
160 Error("Unable to find RGB, Z, double-buffered visual");
163 SetPixelFormat(gHDC, visinfo, &pfd);
164 gCtx = wglCreateContext(gHDC);
165 if (!gCtx) {
166 Error("Couldn't create WGL context");
169 return 0;
172 static struct window *
173 AddWindow(int xpos, int ypos, HGLRC sCtx)
175 struct window *win = &Windows[NumWindows];
176 WNDCLASS wc = {0};
177 int width = 300, height = 300;
179 if (NumWindows >= MAX_WINDOWS)
180 return NULL;
182 memset(win, 0, sizeof(*win));
183 InitializeCriticalSection(&win->drawMutex);
184 win->Angle = 0.0;
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;
193 RegisterClass(&wc);
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");
211 win->sharedContext = sCtx;
213 ShowWindow(win->Win, SW_SHOW);
215 return win;
219 static void
220 InitGLstuff(void)
222 glGenTextures(3, Textures);
224 /* setup first texture object */
226 GLubyte image[16][16][4];
227 GLint i, j;
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++) {
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;
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;
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];
258 GLint i, j;
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++) {
264 if ((i ^ j) & 1) {
265 image[i][j][0] = 0;
266 image[i][j][1] = 255;
267 image[i][j][2] = 0;
269 else {
270 image[i][j][0] = 255;
271 image[i][j][1] = 255;
272 image[i][j][2] = 0;
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];
287 GLint i, j;
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++) {
293 if ((i ^ j) & 1) {
294 image[i][j][0] = 0;
295 image[i][j][1] = 0;
296 image[i][j][2] = 255;
298 else {
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));
320 static void
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");
327 return;
330 h->Angle += 1.0;
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);
340 glColor3f(1, 1, 1);
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();
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();
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();
393 glPopMatrix();
395 SwapBuffers(h->hDC);
397 if (!wglMakeCurrent(NULL, NULL)) {
398 Error("wglMakeCurrent failed in Redraw");
400 LeaveCriticalSection(&h->drawMutex);
403 static DWORD WINAPI
404 threadRunner (void *arg)
406 struct thread_init_arg *tia = (struct thread_init_arg *) arg;
407 struct window *win;
408 PIXELFORMATDESCRIPTOR pfd = {0};
409 int visinfo;
411 win = &Windows[tia->id];
413 win->hDC = GetDC(win->Win);
414 if (!win->hDC) {
415 Error("Couldn't obtain HDC");
418 /* Wait for the previous thread */
419 if(tia->id > 0)
420 WaitForSingleObject(Windows[tia->id - 1].hEventInitialised, INFINITE);
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 struct window *h[MAX_WINDOWS];
512 HANDLE threads[MAX_WINDOWS];
513 int i;
515 terminate = CreateEvent(NULL, TRUE, FALSE, NULL);
517 if (initMainthread())
518 return -1;
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++) {
531 DWORD id;
533 tia[i].id = 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.");
541 return -1;
544 InitGLstuff();
546 while (1) {
547 MSG msg;
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;
555 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
556 if (msg.message == WM_QUIT) {
557 return 0;
559 TranslateMessage(&msg);
560 DispatchMessage(&msg);
564 return 0;