sharedtex_mt.c revision 32001f49
132001f49Smrg/*
232001f49Smrg * Test sharing of display lists and texture objects between GLX contests.
332001f49Smrg * Brian Paul
432001f49Smrg * Summer 2000
532001f49Smrg *
632001f49Smrg *
732001f49Smrg * Copyright (C) 2000  Brian Paul   All Rights Reserved.
832001f49Smrg *
932001f49Smrg * Permission is hereby granted, free of charge, to any person obtaining a
1032001f49Smrg * copy of this software and associated documentation files (the "Software"),
1132001f49Smrg * to deal in the Software without restriction, including without limitation
1232001f49Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1332001f49Smrg * and/or sell copies of the Software, and to permit persons to whom the
1432001f49Smrg * Software is furnished to do so, subject to the following conditions:
1532001f49Smrg *
1632001f49Smrg * The above copyright notice and this permission notice shall be included
1732001f49Smrg * in all copies or substantial portions of the Software.
1832001f49Smrg *
1932001f49Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
2032001f49Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2132001f49Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
2232001f49Smrg * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2332001f49Smrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2432001f49Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2532001f49Smrg *
2632001f49Smrg *
2732001f49Smrg * Modified 2009 for multithreading by Thomas Hellstrom.
2832001f49Smrg *
2932001f49Smrg * Port to windows by Michal Krol.
3032001f49Smrg */
3132001f49Smrg
3232001f49Smrg
3332001f49Smrg#include <windows.h>
3432001f49Smrg#include <GL/gl.h>
3532001f49Smrg#include <stdio.h>
3632001f49Smrg#include <stdlib.h>
3732001f49Smrg#include <string.h>
3832001f49Smrg
3932001f49Smrg#pragma comment(lib, "opengl32.lib")
4032001f49Smrg
4132001f49Smrgstruct thread_init_arg {
4232001f49Smrg   int id;
4332001f49Smrg};
4432001f49Smrg
4532001f49Smrgstruct window {
4632001f49Smrg   CRITICAL_SECTION drawMutex;
4732001f49Smrg   HDC hDC;
4832001f49Smrg   HWND Win;
4932001f49Smrg   HGLRC Context;
5032001f49Smrg   float Angle;
5132001f49Smrg   int Id;
5232001f49Smrg   HGLRC sharedContext;
5332001f49Smrg   HANDLE hEventInitialised;
5432001f49Smrg};
5532001f49Smrg
5632001f49Smrg
5732001f49Smrg#define MAX_WINDOWS 20
5832001f49Smrgstatic struct window Windows[MAX_WINDOWS];
5932001f49Smrgstatic int NumWindows = 0;
6032001f49Smrgstatic HANDLE terminate = NULL;
6132001f49Smrgstatic HGLRC gCtx = NULL;
6232001f49Smrgstatic HDC gHDC = NULL;
6332001f49Smrgstatic GLuint Textures[3];
6432001f49Smrg
6532001f49Smrg
6632001f49Smrg
6732001f49Smrgstatic void
6832001f49SmrgError(const char *msg)
6932001f49Smrg{
7032001f49Smrg   fprintf(stderr, "Error - %s\n", msg);
7132001f49Smrg   exit(1);
7232001f49Smrg}
7332001f49Smrg
7432001f49Smrgstatic void
7532001f49SmrgResize(struct window *h, unsigned int width, unsigned int height);
7632001f49Smrg
7732001f49Smrgstatic LRESULT CALLBACK
7832001f49SmrgWndProc(HWND hWnd,
7932001f49Smrg        UINT uMsg,
8032001f49Smrg        WPARAM wParam,
8132001f49Smrg        LPARAM lParam )
8232001f49Smrg{
8332001f49Smrg   switch (uMsg) {
8432001f49Smrg   case WM_KEYDOWN:
8532001f49Smrg      SetEvent(terminate);
8632001f49Smrg      break;
8732001f49Smrg   case WM_SIZE:
8832001f49Smrg      {
8932001f49Smrg         LONG_PTR index = GetWindowLongPtr(hWnd, GWLP_USERDATA);
9032001f49Smrg
9132001f49Smrg         if (index >= 0 && index < MAX_WINDOWS) {
9232001f49Smrg            RECT r;
9332001f49Smrg
9432001f49Smrg            GetClientRect(hWnd, &r);
9532001f49Smrg            Resize(&Windows[index], r.right, r.bottom);
9632001f49Smrg         }
9732001f49Smrg      }
9832001f49Smrg      break;
9932001f49Smrg   case WM_CREATE:
10032001f49Smrg      {
10132001f49Smrg         CREATESTRUCT *pcs = (CREATESTRUCT *) lParam;
10232001f49Smrg
10332001f49Smrg         SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) pcs->lpCreateParams);
10432001f49Smrg      }
10532001f49Smrg      break;
10632001f49Smrg   case WM_DESTROY:
10732001f49Smrg      PostQuitMessage(0);
10832001f49Smrg      break;
10932001f49Smrg   default:
11032001f49Smrg      return DefWindowProc(hWnd, uMsg, wParam, lParam);
11132001f49Smrg   }
11232001f49Smrg
11332001f49Smrg   return 0;
11432001f49Smrg}
11532001f49Smrg
11632001f49Smrgstatic int
11732001f49SmrginitMainthread(void)
11832001f49Smrg{
11932001f49Smrg   WNDCLASS wc = {0};
12032001f49Smrg   HWND win;
12132001f49Smrg   PIXELFORMATDESCRIPTOR pfd = {0};
12232001f49Smrg   int visinfo;
12332001f49Smrg
12432001f49Smrg   wc.lpfnWndProc = WndProc;
12532001f49Smrg   wc.lpszClassName = "sharedtex_mt.hidden";
12632001f49Smrg   wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
12732001f49Smrg   RegisterClass(&wc);
12832001f49Smrg
12932001f49Smrg   win = CreateWindowEx(0,
13032001f49Smrg                        wc.lpszClassName,
13132001f49Smrg                        "sharedtex_mt.hidden",
13232001f49Smrg                        WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
13332001f49Smrg                        CW_USEDEFAULT,
13432001f49Smrg                        CW_USEDEFAULT,
13532001f49Smrg                        CW_USEDEFAULT,
13632001f49Smrg                        CW_USEDEFAULT,
13732001f49Smrg                        NULL,
13832001f49Smrg                        NULL,
13932001f49Smrg                        wc.hInstance,
14032001f49Smrg                        (LPVOID) -1);
14132001f49Smrg   if (!win) {
14232001f49Smrg      Error("Couldn't create window");
14332001f49Smrg   }
14432001f49Smrg
14532001f49Smrg   gHDC = GetDC(win);
14632001f49Smrg   if (!gHDC) {
14732001f49Smrg      Error("Couldn't obtain HDC");
14832001f49Smrg   }
14932001f49Smrg
15032001f49Smrg   pfd.cColorBits = 24;
15132001f49Smrg   pfd.cDepthBits = 24;
15232001f49Smrg   pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
15332001f49Smrg   pfd.iLayerType = PFD_MAIN_PLANE;
15432001f49Smrg   pfd.iPixelType = PFD_TYPE_RGBA;
15532001f49Smrg   pfd.nSize = sizeof(pfd);
15632001f49Smrg   pfd.nVersion = 1;
15732001f49Smrg
15832001f49Smrg   visinfo = ChoosePixelFormat(gHDC, &pfd);
15932001f49Smrg   if (!visinfo) {
16032001f49Smrg      Error("Unable to find RGB, Z, double-buffered visual");
16132001f49Smrg   }
16232001f49Smrg
16332001f49Smrg   SetPixelFormat(gHDC, visinfo, &pfd);
16432001f49Smrg   gCtx = wglCreateContext(gHDC);
16532001f49Smrg   if (!gCtx) {
16632001f49Smrg      Error("Couldn't create WGL context");
16732001f49Smrg   }
16832001f49Smrg
16932001f49Smrg   return 0;
17032001f49Smrg}
17132001f49Smrg
17232001f49Smrgstatic struct window *
17332001f49SmrgAddWindow(int xpos, int ypos, HGLRC sCtx)
17432001f49Smrg{
17532001f49Smrg   struct window *win = &Windows[NumWindows];
17632001f49Smrg   WNDCLASS wc = {0};
17732001f49Smrg   int width = 300, height = 300;
17832001f49Smrg
17932001f49Smrg   if (NumWindows >= MAX_WINDOWS)
18032001f49Smrg      return NULL;
18132001f49Smrg
18232001f49Smrg   memset(win, 0, sizeof(*win));
18332001f49Smrg   InitializeCriticalSection(&win->drawMutex);
18432001f49Smrg   win->Angle = 0.0;
18532001f49Smrg   win->Id = NumWindows++;
18632001f49Smrg
18732001f49Smrg   wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
18832001f49Smrg   wc.hCursor = LoadCursor(NULL, IDC_ARROW);
18932001f49Smrg   wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
19032001f49Smrg   wc.lpfnWndProc = WndProc;
19132001f49Smrg   wc.lpszClassName = "sharedtex_mt";
19232001f49Smrg   wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
19332001f49Smrg   RegisterClass(&wc);
19432001f49Smrg
19532001f49Smrg   win->Win = CreateWindowEx(0,
19632001f49Smrg                             wc.lpszClassName,
19732001f49Smrg                             "sharedtex_mt",
19832001f49Smrg                             WS_SIZEBOX | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
19932001f49Smrg                             xpos,
20032001f49Smrg                             ypos,
20132001f49Smrg                             width,
20232001f49Smrg                             height,
20332001f49Smrg                             NULL,
20432001f49Smrg                             NULL,
20532001f49Smrg                             wc.hInstance,
20632001f49Smrg                             (LPVOID) win->Id);
20732001f49Smrg   if (!win->Win) {
20832001f49Smrg      Error("Couldn't create window");
20932001f49Smrg   }
21032001f49Smrg
21132001f49Smrg   win->sharedContext = sCtx;
21232001f49Smrg
21332001f49Smrg   ShowWindow(win->Win, SW_SHOW);
21432001f49Smrg
21532001f49Smrg   return win;
21632001f49Smrg}
21732001f49Smrg
21832001f49Smrg
21932001f49Smrgstatic void
22032001f49SmrgInitGLstuff(void)
22132001f49Smrg{
22232001f49Smrg   glGenTextures(3, Textures);
22332001f49Smrg
22432001f49Smrg   /* setup first texture object */
22532001f49Smrg   {
22632001f49Smrg      GLubyte image[16][16][4];
22732001f49Smrg      GLint i, j;
22832001f49Smrg      glBindTexture(GL_TEXTURE_2D, Textures[0]);
22932001f49Smrg
23032001f49Smrg      /* red/white checkerboard */
23132001f49Smrg      for (i = 0; i < 16; i++) {
23232001f49Smrg         for (j = 0; j < 16; j++) {
23332001f49Smrg            if ((i ^ j) & 1) {
23432001f49Smrg               image[i][j][0] = 255;
23532001f49Smrg               image[i][j][1] = 255;
23632001f49Smrg               image[i][j][2] = 255;
23732001f49Smrg               image[i][j][3] = 255;
23832001f49Smrg            }
23932001f49Smrg            else {
24032001f49Smrg               image[i][j][0] = 255;
24132001f49Smrg               image[i][j][1] = 0;
24232001f49Smrg               image[i][j][2] = 0;
24332001f49Smrg               image[i][j][3] = 255;
24432001f49Smrg            }
24532001f49Smrg         }
24632001f49Smrg      }
24732001f49Smrg
24832001f49Smrg      glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
24932001f49Smrg      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
25032001f49Smrg                   GL_UNSIGNED_BYTE, image);
25132001f49Smrg      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
25232001f49Smrg      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
25332001f49Smrg   }
25432001f49Smrg
25532001f49Smrg   /* setup second texture object */
25632001f49Smrg   {
25732001f49Smrg      GLubyte image[8][8][3];
25832001f49Smrg      GLint i, j;
25932001f49Smrg      glBindTexture(GL_TEXTURE_2D, Textures[1]);
26032001f49Smrg
26132001f49Smrg      /* green/yellow checkerboard */
26232001f49Smrg      for (i = 0; i < 8; i++) {
26332001f49Smrg         for (j = 0; j < 8; j++) {
26432001f49Smrg            if ((i ^ j) & 1) {
26532001f49Smrg               image[i][j][0] = 0;
26632001f49Smrg               image[i][j][1] = 255;
26732001f49Smrg               image[i][j][2] = 0;
26832001f49Smrg            }
26932001f49Smrg            else {
27032001f49Smrg               image[i][j][0] = 255;
27132001f49Smrg               image[i][j][1] = 255;
27232001f49Smrg               image[i][j][2] = 0;
27332001f49Smrg            }
27432001f49Smrg         }
27532001f49Smrg      }
27632001f49Smrg
27732001f49Smrg      glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
27832001f49Smrg      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB,
27932001f49Smrg                   GL_UNSIGNED_BYTE, image);
28032001f49Smrg      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
28132001f49Smrg      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
28232001f49Smrg   }
28332001f49Smrg
28432001f49Smrg   /* setup second texture object */
28532001f49Smrg   {
28632001f49Smrg      GLubyte image[4][4][3];
28732001f49Smrg      GLint i, j;
28832001f49Smrg      glBindTexture(GL_TEXTURE_2D, Textures[2]);
28932001f49Smrg
29032001f49Smrg      /* blue/gray checkerboard */
29132001f49Smrg      for (i = 0; i < 4; i++) {
29232001f49Smrg         for (j = 0; j < 4; j++) {
29332001f49Smrg            if ((i ^ j) & 1) {
29432001f49Smrg               image[i][j][0] = 0;
29532001f49Smrg               image[i][j][1] = 0;
29632001f49Smrg               image[i][j][2] = 255;
29732001f49Smrg            }
29832001f49Smrg            else {
29932001f49Smrg               image[i][j][0] = 200;
30032001f49Smrg               image[i][j][1] = 200;
30132001f49Smrg               image[i][j][2] = 200;
30232001f49Smrg            }
30332001f49Smrg         }
30432001f49Smrg      }
30532001f49Smrg
30632001f49Smrg      glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
30732001f49Smrg      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 4, 4, 0, GL_RGB,
30832001f49Smrg                   GL_UNSIGNED_BYTE, image);
30932001f49Smrg      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
31032001f49Smrg      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
31132001f49Smrg   }
31232001f49Smrg
31332001f49Smrg   /* Now make the cube object display list */
31432001f49Smrg
31532001f49Smrg   printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER));
31632001f49Smrg   printf("GL_VERSION: %s\n", (char *) glGetString(GL_VERSION));
31732001f49Smrg   printf("GL_VENDOR: %s\n", (char *) glGetString(GL_VENDOR));
31832001f49Smrg}
31932001f49Smrg
32032001f49Smrgstatic void
32132001f49SmrgRedraw(struct window *h)
32232001f49Smrg{
32332001f49Smrg   EnterCriticalSection(&h->drawMutex);
32432001f49Smrg   if (!wglMakeCurrent(h->hDC, h->Context)) {
32532001f49Smrg      LeaveCriticalSection(&h->drawMutex);
32632001f49Smrg      Error("wglMakeCurrent failed in Redraw");
32732001f49Smrg      return;
32832001f49Smrg   }
32932001f49Smrg
33032001f49Smrg   h->Angle += 1.0;
33132001f49Smrg
33232001f49Smrg   glShadeModel(GL_FLAT);
33332001f49Smrg   glClearColor(0.25, 0.25, 0.25, 1.0);
33432001f49Smrg   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
33532001f49Smrg
33632001f49Smrg   glEnable(GL_TEXTURE_2D);
33732001f49Smrg   glEnable(GL_DEPTH_TEST);
33832001f49Smrg   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
33932001f49Smrg
34032001f49Smrg   glColor3f(1, 1, 1);
34132001f49Smrg
34232001f49Smrg   glPushMatrix();
34332001f49Smrg   if (h->Id == 0)
34432001f49Smrg      glRotatef(h->Angle, 0, 1, -1);
34532001f49Smrg   else if (h->Id == 1)
34632001f49Smrg      glRotatef(-(h->Angle), 0, 1, -1);
34732001f49Smrg   else if (h->Id == 2)
34832001f49Smrg      glRotatef(h->Angle, 0, 1, 1);
34932001f49Smrg   else if (h->Id == 3)
35032001f49Smrg      glRotatef(-(h->Angle), 0, 1, 1);
35132001f49Smrg   glBindTexture(GL_TEXTURE_2D, Textures[0]);
35232001f49Smrg   glBegin(GL_POLYGON);
35332001f49Smrg   glTexCoord2f(0, 0);  glVertex3f(-1, -1, -1);
35432001f49Smrg   glTexCoord2f(1, 0);  glVertex3f(-1,  1, -1);
35532001f49Smrg   glTexCoord2f(1, 1);  glVertex3f(-1,  1,  1);
35632001f49Smrg   glTexCoord2f(0, 1);  glVertex3f(-1, -1,  1);
35732001f49Smrg   glEnd();
35832001f49Smrg   glBegin(GL_POLYGON);
35932001f49Smrg   glTexCoord2f(0, 0);  glVertex3f(1, -1, -1);
36032001f49Smrg   glTexCoord2f(1, 0);  glVertex3f(1,  1, -1);
36132001f49Smrg   glTexCoord2f(1, 1);  glVertex3f(1,  1,  1);
36232001f49Smrg   glTexCoord2f(0, 1);  glVertex3f(1, -1,  1);
36332001f49Smrg   glEnd();
36432001f49Smrg
36532001f49Smrg   glBindTexture(GL_TEXTURE_2D, Textures[1]);
36632001f49Smrg   glBegin(GL_POLYGON);
36732001f49Smrg   glTexCoord2f(0, 0);  glVertex3f(-1, -1, -1);
36832001f49Smrg   glTexCoord2f(1, 0);  glVertex3f( 1, -1, -1);
36932001f49Smrg   glTexCoord2f(1, 1);  glVertex3f( 1, -1,  1);
37032001f49Smrg   glTexCoord2f(0, 1);  glVertex3f(-1, -1,  1);
37132001f49Smrg   glEnd();
37232001f49Smrg   glBegin(GL_POLYGON);
37332001f49Smrg   glTexCoord2f(0, 0);  glVertex3f(-1, 1, -1);
37432001f49Smrg   glTexCoord2f(1, 0);  glVertex3f( 1, 1, -1);
37532001f49Smrg   glTexCoord2f(1, 1);  glVertex3f( 1, 1,  1);
37632001f49Smrg   glTexCoord2f(0, 1);  glVertex3f(-1, 1,  1);
37732001f49Smrg   glEnd();
37832001f49Smrg
37932001f49Smrg   glBindTexture(GL_TEXTURE_2D, Textures[2]);
38032001f49Smrg   glBegin(GL_POLYGON);
38132001f49Smrg   glTexCoord2f(0, 0);  glVertex3f(-1, -1, -1);
38232001f49Smrg   glTexCoord2f(1, 0);  glVertex3f( 1, -1, -1);
38332001f49Smrg   glTexCoord2f(1, 1);  glVertex3f( 1,  1, -1);
38432001f49Smrg   glTexCoord2f(0, 1);  glVertex3f(-1,  1, -1);
38532001f49Smrg   glEnd();
38632001f49Smrg   glBegin(GL_POLYGON);
38732001f49Smrg   glTexCoord2f(0, 0);  glVertex3f(-1, -1, 1);
38832001f49Smrg   glTexCoord2f(1, 0);  glVertex3f( 1, -1, 1);
38932001f49Smrg   glTexCoord2f(1, 1);  glVertex3f( 1,  1, 1);
39032001f49Smrg   glTexCoord2f(0, 1);  glVertex3f(-1,  1, 1);
39132001f49Smrg   glEnd();
39232001f49Smrg
39332001f49Smrg   glPopMatrix();
39432001f49Smrg
39532001f49Smrg   SwapBuffers(h->hDC);
39632001f49Smrg
39732001f49Smrg   if (!wglMakeCurrent(NULL, NULL)) {
39832001f49Smrg      Error("wglMakeCurrent failed in Redraw");
39932001f49Smrg   }
40032001f49Smrg   LeaveCriticalSection(&h->drawMutex);
40132001f49Smrg}
40232001f49Smrg
40332001f49Smrgstatic DWORD WINAPI
40432001f49SmrgthreadRunner (void *arg)
40532001f49Smrg{
40632001f49Smrg   struct thread_init_arg *tia = (struct thread_init_arg *) arg;
40732001f49Smrg   struct window *win;
40832001f49Smrg   PIXELFORMATDESCRIPTOR pfd = {0};
40932001f49Smrg   int visinfo;
41032001f49Smrg
41132001f49Smrg   win = &Windows[tia->id];
41232001f49Smrg
41332001f49Smrg   win->hDC = GetDC(win->Win);
41432001f49Smrg   if (!win->hDC) {
41532001f49Smrg      Error("Couldn't obtain HDC");
41632001f49Smrg   }
41732001f49Smrg
41832001f49Smrg   /* Wait for the previous thread */
41932001f49Smrg   if(tia->id > 0)
42032001f49Smrg      WaitForSingleObject(Windows[tia->id - 1].hEventInitialised, INFINITE);
42132001f49Smrg
42232001f49Smrg   pfd.cColorBits = 24;
42332001f49Smrg   pfd.cDepthBits = 24;
42432001f49Smrg   pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
42532001f49Smrg   pfd.iLayerType = PFD_MAIN_PLANE;
42632001f49Smrg   pfd.iPixelType = PFD_TYPE_RGBA;
42732001f49Smrg   pfd.nSize = sizeof(pfd);
42832001f49Smrg   pfd.nVersion = 1;
42932001f49Smrg
43032001f49Smrg   visinfo = ChoosePixelFormat(win->hDC, &pfd);
43132001f49Smrg   if (!visinfo) {
43232001f49Smrg      Error("Unable to find RGB, Z, double-buffered visual");
43332001f49Smrg   }
43432001f49Smrg
43532001f49Smrg   SetPixelFormat(win->hDC, visinfo, &pfd);
43632001f49Smrg   win->Context = wglCreateContext(win->hDC);
43732001f49Smrg   if (!win->Context) {
43832001f49Smrg      Error("Couldn't create WGL context");
43932001f49Smrg   }
44032001f49Smrg
44132001f49Smrg   if (win->sharedContext) {
44232001f49Smrg      if(!wglShareLists(win->sharedContext, win->Context))
44332001f49Smrg         Error("Couldn't share WGL context lists");
44432001f49Smrg   }
44532001f49Smrg
44632001f49Smrg   SetEvent(win->hEventInitialised);
44732001f49Smrg
44832001f49Smrg   /* Wait for all threads to initialize otherwise wglShareLists will fail */
44932001f49Smrg   if(tia->id < NumWindows - 1)
45032001f49Smrg      WaitForSingleObject(Windows[NumWindows - 1].hEventInitialised, INFINITE);
45132001f49Smrg
45232001f49Smrg   SendMessage(win->Win, WM_SIZE, 0, 0);
45332001f49Smrg
45432001f49Smrg   while (1) {
45532001f49Smrg      MSG msg;
45632001f49Smrg
45732001f49Smrg      /* wait 1 ms for signal either to exit or process messages */
45832001f49Smrg      switch (MsgWaitForMultipleObjects(1, &terminate, FALSE, 1, QS_ALLINPUT)) {
45932001f49Smrg      case WAIT_OBJECT_0:
46032001f49Smrg         SendMessage(win->Win, WM_CLOSE, 0, 0);
46132001f49Smrg         break;
46232001f49Smrg      case WAIT_OBJECT_0 + 1:
46332001f49Smrg         break;
46432001f49Smrg      }
46532001f49Smrg
46632001f49Smrg      while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
46732001f49Smrg         if (msg.message == WM_QUIT) {
46832001f49Smrg            return 0;
46932001f49Smrg         }
47032001f49Smrg         TranslateMessage(&msg);
47132001f49Smrg         DispatchMessage(&msg);
47232001f49Smrg      }
47332001f49Smrg
47432001f49Smrg      Redraw(win);
47532001f49Smrg   }
47632001f49Smrg
47732001f49Smrg   return 0;
47832001f49Smrg}
47932001f49Smrg
48032001f49Smrgstatic void
48132001f49SmrgResize(struct window *h, unsigned int width, unsigned int height)
48232001f49Smrg{
48332001f49Smrg   if (!h->Context)
48432001f49Smrg      return;
48532001f49Smrg
48632001f49Smrg   EnterCriticalSection(&h->drawMutex);
48732001f49Smrg
48832001f49Smrg   if (!wglMakeCurrent(h->hDC, h->Context)) {
48932001f49Smrg      LeaveCriticalSection(&h->drawMutex);
49032001f49Smrg      Error("wglMakeCurrent failed in Resize()");
49132001f49Smrg      return;
49232001f49Smrg   }
49332001f49Smrg
49432001f49Smrg   glViewport(0, 0, width, height);
49532001f49Smrg   glMatrixMode(GL_PROJECTION);
49632001f49Smrg   glLoadIdentity();
49732001f49Smrg   glFrustum(-1, 1, -1, 1, 2, 10);
49832001f49Smrg   glMatrixMode(GL_MODELVIEW);
49932001f49Smrg   glLoadIdentity();
50032001f49Smrg   glTranslatef(0, 0, -4.5);
50132001f49Smrg   if (!wglMakeCurrent(NULL, NULL)) {
50232001f49Smrg      Error("wglMakeCurrent failed in Resize()");
50332001f49Smrg   }
50432001f49Smrg   LeaveCriticalSection(&h->drawMutex);
50532001f49Smrg}
50632001f49Smrg
50732001f49Smrgint
50832001f49Smrgmain(int argc, char *argv[])
50932001f49Smrg{
51032001f49Smrg   struct thread_init_arg tia[MAX_WINDOWS];
51132001f49Smrg   struct window *h[MAX_WINDOWS];
51232001f49Smrg   HANDLE threads[MAX_WINDOWS];
51332001f49Smrg   int i;
51432001f49Smrg
51532001f49Smrg   terminate = CreateEvent(NULL, TRUE, FALSE, NULL);
51632001f49Smrg
51732001f49Smrg   if (initMainthread())
51832001f49Smrg      return -1;
51932001f49Smrg
52032001f49Smrg   /* four windows and contexts sharing display lists and texture objects */
52132001f49Smrg   h[0] = AddWindow( 10,  10, gCtx);
52232001f49Smrg   h[1] = AddWindow(330,  10, gCtx);
52332001f49Smrg   h[2] = AddWindow( 10, 350, gCtx);
52432001f49Smrg   h[3] = AddWindow(330, 350, gCtx);
52532001f49Smrg
52632001f49Smrg   for (i = 0; i < NumWindows; i++) {
52732001f49Smrg      Windows[i].hEventInitialised = CreateEvent(NULL, TRUE, FALSE, NULL);
52832001f49Smrg   }
52932001f49Smrg
53032001f49Smrg   for (i = 0; i < NumWindows; i++) {
53132001f49Smrg      DWORD id;
53232001f49Smrg
53332001f49Smrg      tia[i].id = i;
53432001f49Smrg      threads[i] = CreateThread(NULL, 0, threadRunner, &tia[i], 0, &id);
53532001f49Smrg
53632001f49Smrg      WaitForSingleObject(Windows[i].hEventInitialised, INFINITE);
53732001f49Smrg   }
53832001f49Smrg
53932001f49Smrg   if (!wglMakeCurrent(gHDC, gCtx)) {
54032001f49Smrg      Error("wglMakeCurrent failed for init thread.");
54132001f49Smrg      return -1;
54232001f49Smrg   }
54332001f49Smrg
54432001f49Smrg   InitGLstuff();
54532001f49Smrg
54632001f49Smrg   while (1) {
54732001f49Smrg      MSG msg;
54832001f49Smrg
54932001f49Smrg      /* wait 1 ms for signal either to exit or process messages */
55032001f49Smrg      switch (MsgWaitForMultipleObjects(NumWindows, threads, TRUE, 1, QS_ALLINPUT)) {
55132001f49Smrg      case WAIT_OBJECT_0:
55232001f49Smrg         return 0;
55332001f49Smrg      }
55432001f49Smrg
55532001f49Smrg      while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
55632001f49Smrg         if (msg.message == WM_QUIT) {
55732001f49Smrg            return 0;
55832001f49Smrg         }
55932001f49Smrg         TranslateMessage(&msg);
56032001f49Smrg         DispatchMessage(&msg);
56132001f49Smrg      }
56232001f49Smrg   }
56332001f49Smrg
56432001f49Smrg   return 0;
56532001f49Smrg}
566