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
3932001f49Smrgstruct thread_init_arg {
4032001f49Smrg   int id;
4132001f49Smrg};
4232001f49Smrg
4332001f49Smrgstruct window {
4432001f49Smrg   CRITICAL_SECTION drawMutex;
4532001f49Smrg   HDC hDC;
4632001f49Smrg   HWND Win;
4732001f49Smrg   HGLRC Context;
4832001f49Smrg   float Angle;
4932001f49Smrg   int Id;
5032001f49Smrg   HGLRC sharedContext;
5132001f49Smrg   HANDLE hEventInitialised;
5232001f49Smrg};
5332001f49Smrg
5432001f49Smrg
5532001f49Smrg#define MAX_WINDOWS 20
5632001f49Smrgstatic struct window Windows[MAX_WINDOWS];
5732001f49Smrgstatic int NumWindows = 0;
5832001f49Smrgstatic HANDLE terminate = NULL;
5932001f49Smrgstatic HGLRC gCtx = NULL;
6032001f49Smrgstatic HDC gHDC = NULL;
6132001f49Smrgstatic GLuint Textures[3];
6232001f49Smrg
6332001f49Smrg
6432001f49Smrg
6532001f49Smrgstatic void
6632001f49SmrgError(const char *msg)
6732001f49Smrg{
6832001f49Smrg   fprintf(stderr, "Error - %s\n", msg);
6932001f49Smrg   exit(1);
7032001f49Smrg}
7132001f49Smrg
7232001f49Smrgstatic void
7332001f49SmrgResize(struct window *h, unsigned int width, unsigned int height);
7432001f49Smrg
7532001f49Smrgstatic LRESULT CALLBACK
7632001f49SmrgWndProc(HWND hWnd,
7732001f49Smrg        UINT uMsg,
7832001f49Smrg        WPARAM wParam,
7932001f49Smrg        LPARAM lParam )
8032001f49Smrg{
8132001f49Smrg   switch (uMsg) {
8232001f49Smrg   case WM_KEYDOWN:
8332001f49Smrg      SetEvent(terminate);
8432001f49Smrg      break;
8532001f49Smrg   case WM_SIZE:
8632001f49Smrg      {
8732001f49Smrg         LONG_PTR index = GetWindowLongPtr(hWnd, GWLP_USERDATA);
8832001f49Smrg
8932001f49Smrg         if (index >= 0 && index < MAX_WINDOWS) {
9032001f49Smrg            RECT r;
9132001f49Smrg
9232001f49Smrg            GetClientRect(hWnd, &r);
9332001f49Smrg            Resize(&Windows[index], r.right, r.bottom);
9432001f49Smrg         }
9532001f49Smrg      }
9632001f49Smrg      break;
9732001f49Smrg   case WM_CREATE:
9832001f49Smrg      {
9932001f49Smrg         CREATESTRUCT *pcs = (CREATESTRUCT *) lParam;
10032001f49Smrg
10132001f49Smrg         SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) pcs->lpCreateParams);
10232001f49Smrg      }
10332001f49Smrg      break;
10432001f49Smrg   case WM_DESTROY:
10532001f49Smrg      PostQuitMessage(0);
10632001f49Smrg      break;
10732001f49Smrg   default:
10832001f49Smrg      return DefWindowProc(hWnd, uMsg, wParam, lParam);
10932001f49Smrg   }
11032001f49Smrg
11132001f49Smrg   return 0;
11232001f49Smrg}
11332001f49Smrg
11432001f49Smrgstatic int
11532001f49SmrginitMainthread(void)
11632001f49Smrg{
11732001f49Smrg   WNDCLASS wc = {0};
11832001f49Smrg   HWND win;
1197ec3b29aSmrg   PIXELFORMATDESCRIPTOR pfd;
12032001f49Smrg   int visinfo;
12132001f49Smrg
12232001f49Smrg   wc.lpfnWndProc = WndProc;
12332001f49Smrg   wc.lpszClassName = "sharedtex_mt.hidden";
12432001f49Smrg   wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
12532001f49Smrg   RegisterClass(&wc);
12632001f49Smrg
12732001f49Smrg   win = CreateWindowEx(0,
12832001f49Smrg                        wc.lpszClassName,
12932001f49Smrg                        "sharedtex_mt.hidden",
13032001f49Smrg                        WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
13132001f49Smrg                        CW_USEDEFAULT,
13232001f49Smrg                        CW_USEDEFAULT,
13332001f49Smrg                        CW_USEDEFAULT,
13432001f49Smrg                        CW_USEDEFAULT,
13532001f49Smrg                        NULL,
13632001f49Smrg                        NULL,
13732001f49Smrg                        wc.hInstance,
13832001f49Smrg                        (LPVOID) -1);
13932001f49Smrg   if (!win) {
14032001f49Smrg      Error("Couldn't create window");
14132001f49Smrg   }
14232001f49Smrg
14332001f49Smrg   gHDC = GetDC(win);
14432001f49Smrg   if (!gHDC) {
14532001f49Smrg      Error("Couldn't obtain HDC");
14632001f49Smrg   }
14732001f49Smrg
1487ec3b29aSmrg   memset(&pfd, 0, sizeof(pfd));
14932001f49Smrg   pfd.cColorBits = 24;
15032001f49Smrg   pfd.cDepthBits = 24;
15132001f49Smrg   pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
15232001f49Smrg   pfd.iLayerType = PFD_MAIN_PLANE;
15332001f49Smrg   pfd.iPixelType = PFD_TYPE_RGBA;
15432001f49Smrg   pfd.nSize = sizeof(pfd);
15532001f49Smrg   pfd.nVersion = 1;
15632001f49Smrg
15732001f49Smrg   visinfo = ChoosePixelFormat(gHDC, &pfd);
15832001f49Smrg   if (!visinfo) {
15932001f49Smrg      Error("Unable to find RGB, Z, double-buffered visual");
16032001f49Smrg   }
16132001f49Smrg
16232001f49Smrg   SetPixelFormat(gHDC, visinfo, &pfd);
16332001f49Smrg   gCtx = wglCreateContext(gHDC);
16432001f49Smrg   if (!gCtx) {
16532001f49Smrg      Error("Couldn't create WGL context");
16632001f49Smrg   }
16732001f49Smrg
16832001f49Smrg   return 0;
16932001f49Smrg}
17032001f49Smrg
17132001f49Smrgstatic struct window *
17232001f49SmrgAddWindow(int xpos, int ypos, HGLRC sCtx)
17332001f49Smrg{
17432001f49Smrg   struct window *win = &Windows[NumWindows];
17532001f49Smrg   WNDCLASS wc = {0};
17632001f49Smrg   int width = 300, height = 300;
17732001f49Smrg
17832001f49Smrg   if (NumWindows >= MAX_WINDOWS)
17932001f49Smrg      return NULL;
18032001f49Smrg
18132001f49Smrg   memset(win, 0, sizeof(*win));
18232001f49Smrg   InitializeCriticalSection(&win->drawMutex);
18332001f49Smrg   win->Angle = 0.0;
18432001f49Smrg   win->Id = NumWindows++;
18532001f49Smrg
18632001f49Smrg   wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
18732001f49Smrg   wc.hCursor = LoadCursor(NULL, IDC_ARROW);
18832001f49Smrg   wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
18932001f49Smrg   wc.lpfnWndProc = WndProc;
19032001f49Smrg   wc.lpszClassName = "sharedtex_mt";
19132001f49Smrg   wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
19232001f49Smrg   RegisterClass(&wc);
19332001f49Smrg
19432001f49Smrg   win->Win = CreateWindowEx(0,
19532001f49Smrg                             wc.lpszClassName,
19632001f49Smrg                             "sharedtex_mt",
19732001f49Smrg                             WS_SIZEBOX | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
19832001f49Smrg                             xpos,
19932001f49Smrg                             ypos,
20032001f49Smrg                             width,
20132001f49Smrg                             height,
20232001f49Smrg                             NULL,
20332001f49Smrg                             NULL,
20432001f49Smrg                             wc.hInstance,
20532001f49Smrg                             (LPVOID) win->Id);
20632001f49Smrg   if (!win->Win) {
20732001f49Smrg      Error("Couldn't create window");
20832001f49Smrg   }
20932001f49Smrg
21032001f49Smrg   win->sharedContext = sCtx;
21132001f49Smrg
21232001f49Smrg   ShowWindow(win->Win, SW_SHOW);
21332001f49Smrg
21432001f49Smrg   return win;
21532001f49Smrg}
21632001f49Smrg
21732001f49Smrg
21832001f49Smrgstatic void
21932001f49SmrgInitGLstuff(void)
22032001f49Smrg{
22132001f49Smrg   glGenTextures(3, Textures);
22232001f49Smrg
22332001f49Smrg   /* setup first texture object */
22432001f49Smrg   {
22532001f49Smrg      GLubyte image[16][16][4];
22632001f49Smrg      GLint i, j;
22732001f49Smrg      glBindTexture(GL_TEXTURE_2D, Textures[0]);
22832001f49Smrg
22932001f49Smrg      /* red/white checkerboard */
23032001f49Smrg      for (i = 0; i < 16; i++) {
23132001f49Smrg         for (j = 0; j < 16; j++) {
23232001f49Smrg            if ((i ^ j) & 1) {
23332001f49Smrg               image[i][j][0] = 255;
23432001f49Smrg               image[i][j][1] = 255;
23532001f49Smrg               image[i][j][2] = 255;
23632001f49Smrg               image[i][j][3] = 255;
23732001f49Smrg            }
23832001f49Smrg            else {
23932001f49Smrg               image[i][j][0] = 255;
24032001f49Smrg               image[i][j][1] = 0;
24132001f49Smrg               image[i][j][2] = 0;
24232001f49Smrg               image[i][j][3] = 255;
24332001f49Smrg            }
24432001f49Smrg         }
24532001f49Smrg      }
24632001f49Smrg
24732001f49Smrg      glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
24832001f49Smrg      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA,
24932001f49Smrg                   GL_UNSIGNED_BYTE, image);
25032001f49Smrg      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
25132001f49Smrg      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
25232001f49Smrg   }
25332001f49Smrg
25432001f49Smrg   /* setup second texture object */
25532001f49Smrg   {
25632001f49Smrg      GLubyte image[8][8][3];
25732001f49Smrg      GLint i, j;
25832001f49Smrg      glBindTexture(GL_TEXTURE_2D, Textures[1]);
25932001f49Smrg
26032001f49Smrg      /* green/yellow checkerboard */
26132001f49Smrg      for (i = 0; i < 8; i++) {
26232001f49Smrg         for (j = 0; j < 8; j++) {
26332001f49Smrg            if ((i ^ j) & 1) {
26432001f49Smrg               image[i][j][0] = 0;
26532001f49Smrg               image[i][j][1] = 255;
26632001f49Smrg               image[i][j][2] = 0;
26732001f49Smrg            }
26832001f49Smrg            else {
26932001f49Smrg               image[i][j][0] = 255;
27032001f49Smrg               image[i][j][1] = 255;
27132001f49Smrg               image[i][j][2] = 0;
27232001f49Smrg            }
27332001f49Smrg         }
27432001f49Smrg      }
27532001f49Smrg
27632001f49Smrg      glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
27732001f49Smrg      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB,
27832001f49Smrg                   GL_UNSIGNED_BYTE, image);
27932001f49Smrg      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
28032001f49Smrg      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
28132001f49Smrg   }
28232001f49Smrg
28332001f49Smrg   /* setup second texture object */
28432001f49Smrg   {
28532001f49Smrg      GLubyte image[4][4][3];
28632001f49Smrg      GLint i, j;
28732001f49Smrg      glBindTexture(GL_TEXTURE_2D, Textures[2]);
28832001f49Smrg
28932001f49Smrg      /* blue/gray checkerboard */
29032001f49Smrg      for (i = 0; i < 4; i++) {
29132001f49Smrg         for (j = 0; j < 4; j++) {
29232001f49Smrg            if ((i ^ j) & 1) {
29332001f49Smrg               image[i][j][0] = 0;
29432001f49Smrg               image[i][j][1] = 0;
29532001f49Smrg               image[i][j][2] = 255;
29632001f49Smrg            }
29732001f49Smrg            else {
29832001f49Smrg               image[i][j][0] = 200;
29932001f49Smrg               image[i][j][1] = 200;
30032001f49Smrg               image[i][j][2] = 200;
30132001f49Smrg            }
30232001f49Smrg         }
30332001f49Smrg      }
30432001f49Smrg
30532001f49Smrg      glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
30632001f49Smrg      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 4, 4, 0, GL_RGB,
30732001f49Smrg                   GL_UNSIGNED_BYTE, image);
30832001f49Smrg      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
30932001f49Smrg      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
31032001f49Smrg   }
31132001f49Smrg
31232001f49Smrg   /* Now make the cube object display list */
31332001f49Smrg
31432001f49Smrg   printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER));
31532001f49Smrg   printf("GL_VERSION: %s\n", (char *) glGetString(GL_VERSION));
31632001f49Smrg   printf("GL_VENDOR: %s\n", (char *) glGetString(GL_VENDOR));
31732001f49Smrg}
31832001f49Smrg
31932001f49Smrgstatic void
32032001f49SmrgRedraw(struct window *h)
32132001f49Smrg{
32232001f49Smrg   EnterCriticalSection(&h->drawMutex);
32332001f49Smrg   if (!wglMakeCurrent(h->hDC, h->Context)) {
32432001f49Smrg      LeaveCriticalSection(&h->drawMutex);
32532001f49Smrg      Error("wglMakeCurrent failed in Redraw");
32632001f49Smrg      return;
32732001f49Smrg   }
32832001f49Smrg
32932001f49Smrg   h->Angle += 1.0;
33032001f49Smrg
33132001f49Smrg   glShadeModel(GL_FLAT);
33232001f49Smrg   glClearColor(0.25, 0.25, 0.25, 1.0);
33332001f49Smrg   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
33432001f49Smrg
33532001f49Smrg   glEnable(GL_TEXTURE_2D);
33632001f49Smrg   glEnable(GL_DEPTH_TEST);
33732001f49Smrg   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
33832001f49Smrg
33932001f49Smrg   glColor3f(1, 1, 1);
34032001f49Smrg
34132001f49Smrg   glPushMatrix();
34232001f49Smrg   if (h->Id == 0)
34332001f49Smrg      glRotatef(h->Angle, 0, 1, -1);
34432001f49Smrg   else if (h->Id == 1)
34532001f49Smrg      glRotatef(-(h->Angle), 0, 1, -1);
34632001f49Smrg   else if (h->Id == 2)
34732001f49Smrg      glRotatef(h->Angle, 0, 1, 1);
34832001f49Smrg   else if (h->Id == 3)
34932001f49Smrg      glRotatef(-(h->Angle), 0, 1, 1);
35032001f49Smrg   glBindTexture(GL_TEXTURE_2D, Textures[0]);
35132001f49Smrg   glBegin(GL_POLYGON);
35232001f49Smrg   glTexCoord2f(0, 0);  glVertex3f(-1, -1, -1);
35332001f49Smrg   glTexCoord2f(1, 0);  glVertex3f(-1,  1, -1);
35432001f49Smrg   glTexCoord2f(1, 1);  glVertex3f(-1,  1,  1);
35532001f49Smrg   glTexCoord2f(0, 1);  glVertex3f(-1, -1,  1);
35632001f49Smrg   glEnd();
35732001f49Smrg   glBegin(GL_POLYGON);
35832001f49Smrg   glTexCoord2f(0, 0);  glVertex3f(1, -1, -1);
35932001f49Smrg   glTexCoord2f(1, 0);  glVertex3f(1,  1, -1);
36032001f49Smrg   glTexCoord2f(1, 1);  glVertex3f(1,  1,  1);
36132001f49Smrg   glTexCoord2f(0, 1);  glVertex3f(1, -1,  1);
36232001f49Smrg   glEnd();
36332001f49Smrg
36432001f49Smrg   glBindTexture(GL_TEXTURE_2D, Textures[1]);
36532001f49Smrg   glBegin(GL_POLYGON);
36632001f49Smrg   glTexCoord2f(0, 0);  glVertex3f(-1, -1, -1);
36732001f49Smrg   glTexCoord2f(1, 0);  glVertex3f( 1, -1, -1);
36832001f49Smrg   glTexCoord2f(1, 1);  glVertex3f( 1, -1,  1);
36932001f49Smrg   glTexCoord2f(0, 1);  glVertex3f(-1, -1,  1);
37032001f49Smrg   glEnd();
37132001f49Smrg   glBegin(GL_POLYGON);
37232001f49Smrg   glTexCoord2f(0, 0);  glVertex3f(-1, 1, -1);
37332001f49Smrg   glTexCoord2f(1, 0);  glVertex3f( 1, 1, -1);
37432001f49Smrg   glTexCoord2f(1, 1);  glVertex3f( 1, 1,  1);
37532001f49Smrg   glTexCoord2f(0, 1);  glVertex3f(-1, 1,  1);
37632001f49Smrg   glEnd();
37732001f49Smrg
37832001f49Smrg   glBindTexture(GL_TEXTURE_2D, Textures[2]);
37932001f49Smrg   glBegin(GL_POLYGON);
38032001f49Smrg   glTexCoord2f(0, 0);  glVertex3f(-1, -1, -1);
38132001f49Smrg   glTexCoord2f(1, 0);  glVertex3f( 1, -1, -1);
38232001f49Smrg   glTexCoord2f(1, 1);  glVertex3f( 1,  1, -1);
38332001f49Smrg   glTexCoord2f(0, 1);  glVertex3f(-1,  1, -1);
38432001f49Smrg   glEnd();
38532001f49Smrg   glBegin(GL_POLYGON);
38632001f49Smrg   glTexCoord2f(0, 0);  glVertex3f(-1, -1, 1);
38732001f49Smrg   glTexCoord2f(1, 0);  glVertex3f( 1, -1, 1);
38832001f49Smrg   glTexCoord2f(1, 1);  glVertex3f( 1,  1, 1);
38932001f49Smrg   glTexCoord2f(0, 1);  glVertex3f(-1,  1, 1);
39032001f49Smrg   glEnd();
39132001f49Smrg
39232001f49Smrg   glPopMatrix();
39332001f49Smrg
39432001f49Smrg   SwapBuffers(h->hDC);
39532001f49Smrg
39632001f49Smrg   if (!wglMakeCurrent(NULL, NULL)) {
39732001f49Smrg      Error("wglMakeCurrent failed in Redraw");
39832001f49Smrg   }
39932001f49Smrg   LeaveCriticalSection(&h->drawMutex);
40032001f49Smrg}
40132001f49Smrg
40232001f49Smrgstatic DWORD WINAPI
40332001f49SmrgthreadRunner (void *arg)
40432001f49Smrg{
40532001f49Smrg   struct thread_init_arg *tia = (struct thread_init_arg *) arg;
40632001f49Smrg   struct window *win;
4077ec3b29aSmrg   PIXELFORMATDESCRIPTOR pfd;
40832001f49Smrg   int visinfo;
40932001f49Smrg
41032001f49Smrg   win = &Windows[tia->id];
41132001f49Smrg
41232001f49Smrg   win->hDC = GetDC(win->Win);
41332001f49Smrg   if (!win->hDC) {
41432001f49Smrg      Error("Couldn't obtain HDC");
41532001f49Smrg   }
41632001f49Smrg
41732001f49Smrg   /* Wait for the previous thread */
41832001f49Smrg   if(tia->id > 0)
41932001f49Smrg      WaitForSingleObject(Windows[tia->id - 1].hEventInitialised, INFINITE);
42032001f49Smrg
4217ec3b29aSmrg   memset(&pfd, 0, sizeof(pfd));
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   HANDLE threads[MAX_WINDOWS];
51232001f49Smrg   int i;
51332001f49Smrg
51432001f49Smrg   terminate = CreateEvent(NULL, TRUE, FALSE, NULL);
51532001f49Smrg
51632001f49Smrg   if (initMainthread())
51732001f49Smrg      return -1;
51832001f49Smrg
51932001f49Smrg   /* four windows and contexts sharing display lists and texture objects */
5207ec3b29aSmrg   AddWindow( 10,  10, gCtx);
5217ec3b29aSmrg   AddWindow(330,  10, gCtx);
5227ec3b29aSmrg   AddWindow( 10, 350, gCtx);
5237ec3b29aSmrg   AddWindow(330, 350, gCtx);
52432001f49Smrg
52532001f49Smrg   for (i = 0; i < NumWindows; i++) {
52632001f49Smrg      Windows[i].hEventInitialised = CreateEvent(NULL, TRUE, FALSE, NULL);
52732001f49Smrg   }
52832001f49Smrg
52932001f49Smrg   for (i = 0; i < NumWindows; i++) {
53032001f49Smrg      DWORD id;
53132001f49Smrg
53232001f49Smrg      tia[i].id = i;
53332001f49Smrg      threads[i] = CreateThread(NULL, 0, threadRunner, &tia[i], 0, &id);
53432001f49Smrg
53532001f49Smrg      WaitForSingleObject(Windows[i].hEventInitialised, INFINITE);
53632001f49Smrg   }
53732001f49Smrg
53832001f49Smrg   if (!wglMakeCurrent(gHDC, gCtx)) {
53932001f49Smrg      Error("wglMakeCurrent failed for init thread.");
54032001f49Smrg      return -1;
54132001f49Smrg   }
54232001f49Smrg
54332001f49Smrg   InitGLstuff();
54432001f49Smrg
54532001f49Smrg   while (1) {
54632001f49Smrg      MSG msg;
54732001f49Smrg
54832001f49Smrg      /* wait 1 ms for signal either to exit or process messages */
54932001f49Smrg      switch (MsgWaitForMultipleObjects(NumWindows, threads, TRUE, 1, QS_ALLINPUT)) {
55032001f49Smrg      case WAIT_OBJECT_0:
55132001f49Smrg         return 0;
55232001f49Smrg      }
55332001f49Smrg
55432001f49Smrg      while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
55532001f49Smrg         if (msg.message == WM_QUIT) {
55632001f49Smrg            return 0;
55732001f49Smrg         }
55832001f49Smrg         TranslateMessage(&msg);
55932001f49Smrg         DispatchMessage(&msg);
56032001f49Smrg      }
56132001f49Smrg   }
56232001f49Smrg
56332001f49Smrg   return 0;
56432001f49Smrg}
565