17ec3b29aSmrg/* $Id: sharedtex_mt.c,v 1.1.1.2 2019/03/11 06:59:40 mrg Exp $ */ 232001f49Smrg 332001f49Smrg/* 432001f49Smrg * Test sharing of display lists and texture objects between GLX contests. 532001f49Smrg * Brian Paul 632001f49Smrg * Summer 2000 732001f49Smrg * 832001f49Smrg * 932001f49Smrg * Copyright (C) 2000 Brian Paul All Rights Reserved. 1032001f49Smrg * 1132001f49Smrg * Permission is hereby granted, free of charge, to any person obtaining a 1232001f49Smrg * copy of this software and associated documentation files (the "Software"), 1332001f49Smrg * to deal in the Software without restriction, including without limitation 1432001f49Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1532001f49Smrg * and/or sell copies of the Software, and to permit persons to whom the 1632001f49Smrg * Software is furnished to do so, subject to the following conditions: 1732001f49Smrg * 1832001f49Smrg * The above copyright notice and this permission notice shall be included 1932001f49Smrg * in all copies or substantial portions of the Software. 2032001f49Smrg * 2132001f49Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 2232001f49Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2332001f49Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2432001f49Smrg * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 2532001f49Smrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 2632001f49Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2732001f49Smrg * 2832001f49Smrg * 2932001f49Smrg * Modified 2009 for multithreading by Thomas Hellstrom. 3032001f49Smrg */ 3132001f49Smrg 3232001f49Smrg 3332001f49Smrg#include <GL/gl.h> 3432001f49Smrg#include <GL/glx.h> 3532001f49Smrg#include <stdio.h> 3632001f49Smrg#include <stdlib.h> 3732001f49Smrg#include <unistd.h> 3832001f49Smrg#include <string.h> 3932001f49Smrg#include <pthread.h> 4032001f49Smrg#include <X11/X.h> 4132001f49Smrg 4232001f49Smrgstruct thread_init_arg { 4332001f49Smrg int id; 4432001f49Smrg}; 4532001f49Smrg 4632001f49Smrgstruct window { 4732001f49Smrg pthread_mutex_t drawMutex; 4832001f49Smrg char DisplayName[1000]; 4932001f49Smrg Display *Dpy; 5032001f49Smrg Window Win; 5132001f49Smrg GLXContext Context; 5232001f49Smrg float Angle; 5332001f49Smrg int Id; 5432001f49Smrg XVisualInfo *visInfo; 5532001f49Smrg}; 5632001f49Smrg 5732001f49Smrg 5832001f49Smrg#define MAX_WINDOWS 20 5932001f49Smrgstatic struct window Windows[MAX_WINDOWS]; 6032001f49Smrgstatic int NumWindows = 0; 6132001f49Smrgstatic int terminate = 0; 6232001f49Smrgstatic GLXContext gCtx; 6332001f49Smrgstatic Display *gDpy; 6432001f49Smrgstatic GLuint Textures[3]; 6532001f49Smrg 6632001f49Smrg 6732001f49Smrg 6832001f49Smrgstatic void 6932001f49SmrgError(const char *display, const char *msg) 7032001f49Smrg{ 7132001f49Smrg fprintf(stderr, "Error on display %s - %s\n", display, msg); 7232001f49Smrg exit(1); 7332001f49Smrg} 7432001f49Smrg 7532001f49Smrg 7632001f49Smrgstatic int 7732001f49SmrginitMainthread(Display *dpy, const char *displayName) 7832001f49Smrg{ 7932001f49Smrg int scrnum; 8032001f49Smrg XVisualInfo *visinfo; 8132001f49Smrg int attrib[] = { GLX_RGBA, 8232001f49Smrg GLX_RED_SIZE, 1, 8332001f49Smrg GLX_GREEN_SIZE, 1, 8432001f49Smrg GLX_BLUE_SIZE, 1, 8532001f49Smrg GLX_DOUBLEBUFFER, 8632001f49Smrg GLX_DEPTH_SIZE, 1, 8732001f49Smrg None }; 8832001f49Smrg 8932001f49Smrg scrnum = DefaultScreen(dpy); 9032001f49Smrg visinfo = glXChooseVisual(dpy, scrnum, attrib); 9132001f49Smrg if (!visinfo) { 9232001f49Smrg Error(displayName, "Unable to find RGB, double-buffered visual"); 9332001f49Smrg return -1; 9432001f49Smrg } 9532001f49Smrg gCtx = glXCreateContext(dpy, visinfo, NULL, True); 9632001f49Smrg if (!gCtx) { 9732001f49Smrg Error(displayName, "Couldn't create GLX context"); 9832001f49Smrg return -1; 9932001f49Smrg } 10032001f49Smrg return 0; 10132001f49Smrg} 10232001f49Smrg 10332001f49Smrgstatic struct window * 10432001f49SmrgAddWindow(Display *dpy, const char *displayName, int xpos, int ypos, 10532001f49Smrg GLXContext sCtx) 10632001f49Smrg{ 10732001f49Smrg Window win; 10832001f49Smrg GLXContext ctx; 10932001f49Smrg int attrib[] = { GLX_RGBA, 11032001f49Smrg GLX_RED_SIZE, 1, 11132001f49Smrg GLX_GREEN_SIZE, 1, 11232001f49Smrg GLX_BLUE_SIZE, 1, 11332001f49Smrg GLX_DOUBLEBUFFER, 11432001f49Smrg GLX_DEPTH_SIZE, 1, 11532001f49Smrg None }; 11632001f49Smrg int scrnum; 11732001f49Smrg XSetWindowAttributes attr; 11832001f49Smrg unsigned long mask; 11932001f49Smrg Window root; 12032001f49Smrg XVisualInfo *visinfo; 12132001f49Smrg int width = 300, height = 300; 12232001f49Smrg 12332001f49Smrg if (NumWindows >= MAX_WINDOWS) 12432001f49Smrg return NULL; 12532001f49Smrg 12632001f49Smrg scrnum = DefaultScreen(dpy); 12732001f49Smrg root = RootWindow(dpy, scrnum); 12832001f49Smrg 12932001f49Smrg visinfo = glXChooseVisual(dpy, scrnum, attrib); 13032001f49Smrg if (!visinfo) { 13132001f49Smrg Error(displayName, "Unable to find RGB, double-buffered visual"); 13232001f49Smrg return NULL; 13332001f49Smrg } 13432001f49Smrg 13532001f49Smrg /* window attributes */ 13632001f49Smrg attr.background_pixel = 0; 13732001f49Smrg attr.border_pixel = 0; 13832001f49Smrg attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone); 13932001f49Smrg attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; 14032001f49Smrg mask = CWBorderPixel | CWColormap | CWEventMask; 14132001f49Smrg 14232001f49Smrg win = XCreateWindow(dpy, root, xpos, ypos, width, height, 14332001f49Smrg 0, visinfo->depth, InputOutput, 14432001f49Smrg visinfo->visual, mask, &attr); 14532001f49Smrg if (!win) { 14632001f49Smrg Error(displayName, "Couldn't create window"); 14732001f49Smrg return NULL; 14832001f49Smrg } 14932001f49Smrg 15032001f49Smrg { 15132001f49Smrg XSizeHints sizehints; 15232001f49Smrg sizehints.x = xpos; 15332001f49Smrg sizehints.y = ypos; 15432001f49Smrg sizehints.width = width; 15532001f49Smrg sizehints.height = height; 15632001f49Smrg sizehints.flags = USSize | USPosition; 15732001f49Smrg XSetNormalHints(dpy, win, &sizehints); 15832001f49Smrg XSetStandardProperties(dpy, win, displayName, displayName, 15932001f49Smrg None, (char **)NULL, 0, &sizehints); 16032001f49Smrg } 16132001f49Smrg 16232001f49Smrg 16332001f49Smrg ctx = glXCreateContext(dpy, visinfo, 16432001f49Smrg sCtx ? sCtx : NULL, True); 16532001f49Smrg 16632001f49Smrg if (!ctx) { 16732001f49Smrg Error(displayName, "Couldn't create GLX context"); 16832001f49Smrg return NULL; 16932001f49Smrg } 17032001f49Smrg 17132001f49Smrg XMapWindow(dpy, win); 17232001f49Smrg 17332001f49Smrg /* save the info for this window */ 17432001f49Smrg { 17532001f49Smrg static int id = 0; 17632001f49Smrg struct window *h = &Windows[NumWindows]; 17732001f49Smrg if (strlen(displayName) + 1 > sizeof(h->DisplayName)) { 17832001f49Smrg Error(displayName, "string overflow"); 17932001f49Smrg return NULL; 18032001f49Smrg } 18132001f49Smrg strcpy(h->DisplayName, displayName); 18232001f49Smrg h->Dpy = dpy; 18332001f49Smrg h->Win = win; 18432001f49Smrg h->Context = ctx; 18532001f49Smrg h->Angle = 0.0; 18632001f49Smrg h->Id = id++; 18732001f49Smrg h->visInfo = visinfo; 18832001f49Smrg pthread_mutex_init(&h->drawMutex, NULL); 18932001f49Smrg NumWindows++; 19032001f49Smrg return &Windows[NumWindows-1]; 19132001f49Smrg } 19232001f49Smrg} 19332001f49Smrg 19432001f49Smrg 19532001f49Smrgstatic void 19632001f49SmrgInitGLstuff(void) 19732001f49Smrg 19832001f49Smrg{ 19932001f49Smrg glGenTextures(3, Textures); 20032001f49Smrg 20132001f49Smrg /* setup first texture object */ 20232001f49Smrg { 20332001f49Smrg GLubyte image[16][16][4]; 20432001f49Smrg GLint i, j; 20532001f49Smrg glBindTexture(GL_TEXTURE_2D, Textures[0]); 20632001f49Smrg 20732001f49Smrg /* red/white checkerboard */ 20832001f49Smrg for (i = 0; i < 16; i++) { 20932001f49Smrg for (j = 0; j < 16; j++) { 21032001f49Smrg if ((i ^ j) & 1) { 21132001f49Smrg image[i][j][0] = 255; 21232001f49Smrg image[i][j][1] = 255; 21332001f49Smrg image[i][j][2] = 255; 21432001f49Smrg image[i][j][3] = 255; 21532001f49Smrg } 21632001f49Smrg else { 21732001f49Smrg image[i][j][0] = 255; 21832001f49Smrg image[i][j][1] = 0; 21932001f49Smrg image[i][j][2] = 0; 22032001f49Smrg image[i][j][3] = 255; 22132001f49Smrg } 22232001f49Smrg } 22332001f49Smrg } 22432001f49Smrg 22532001f49Smrg glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 22632001f49Smrg glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, 22732001f49Smrg GL_UNSIGNED_BYTE, image); 22832001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 22932001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 23032001f49Smrg } 23132001f49Smrg 23232001f49Smrg /* setup second texture object */ 23332001f49Smrg { 23432001f49Smrg GLubyte image[8][8][3]; 23532001f49Smrg GLint i, j; 23632001f49Smrg glBindTexture(GL_TEXTURE_2D, Textures[1]); 23732001f49Smrg 23832001f49Smrg /* green/yellow checkerboard */ 23932001f49Smrg for (i = 0; i < 8; i++) { 24032001f49Smrg for (j = 0; j < 8; j++) { 24132001f49Smrg if ((i ^ j) & 1) { 24232001f49Smrg image[i][j][0] = 0; 24332001f49Smrg image[i][j][1] = 255; 24432001f49Smrg image[i][j][2] = 0; 24532001f49Smrg } 24632001f49Smrg else { 24732001f49Smrg image[i][j][0] = 255; 24832001f49Smrg image[i][j][1] = 255; 24932001f49Smrg image[i][j][2] = 0; 25032001f49Smrg } 25132001f49Smrg } 25232001f49Smrg } 25332001f49Smrg 25432001f49Smrg glPixelStorei(GL_UNPACK_ALIGNMENT, 2); 25532001f49Smrg glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, 25632001f49Smrg GL_UNSIGNED_BYTE, image); 25732001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 25832001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 25932001f49Smrg } 26032001f49Smrg 26132001f49Smrg /* setup second texture object */ 26232001f49Smrg { 26332001f49Smrg GLubyte image[4][4][3]; 26432001f49Smrg GLint i, j; 26532001f49Smrg glBindTexture(GL_TEXTURE_2D, Textures[2]); 26632001f49Smrg 26732001f49Smrg /* blue/gray checkerboard */ 26832001f49Smrg for (i = 0; i < 4; i++) { 26932001f49Smrg for (j = 0; j < 4; j++) { 27032001f49Smrg if ((i ^ j) & 1) { 27132001f49Smrg image[i][j][0] = 0; 27232001f49Smrg image[i][j][1] = 0; 27332001f49Smrg image[i][j][2] = 255; 27432001f49Smrg } 27532001f49Smrg else { 27632001f49Smrg image[i][j][0] = 200; 27732001f49Smrg image[i][j][1] = 200; 27832001f49Smrg image[i][j][2] = 200; 27932001f49Smrg } 28032001f49Smrg } 28132001f49Smrg } 28232001f49Smrg 28332001f49Smrg glPixelStorei(GL_UNPACK_ALIGNMENT, 2); 28432001f49Smrg glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 4, 4, 0, GL_RGB, 28532001f49Smrg GL_UNSIGNED_BYTE, image); 28632001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 28732001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 28832001f49Smrg } 28932001f49Smrg 29032001f49Smrg /* Now make the cube object display list */ 29132001f49Smrg 29232001f49Smrg printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER)); 29332001f49Smrg printf("GL_VERSION: %s\n", (char *) glGetString(GL_VERSION)); 29432001f49Smrg printf("GL_VENDOR: %s\n", (char *) glGetString(GL_VENDOR)); 29532001f49Smrg} 29632001f49Smrg 29732001f49Smrgstatic void 29832001f49SmrgRedraw(struct window *h) 29932001f49Smrg{ 30032001f49Smrg pthread_mutex_lock(&h->drawMutex); 30132001f49Smrg if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) { 30232001f49Smrg Error(h->DisplayName, "glXMakeCurrent failed in Redraw"); 30332001f49Smrg pthread_mutex_unlock(&h->drawMutex); 30432001f49Smrg return; 30532001f49Smrg } 30632001f49Smrg 30732001f49Smrg h->Angle += 1.0; 30832001f49Smrg 30932001f49Smrg glShadeModel(GL_FLAT); 31032001f49Smrg glClearColor(0.25, 0.25, 0.25, 1.0); 31132001f49Smrg glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 31232001f49Smrg 31332001f49Smrg glEnable(GL_TEXTURE_2D); 31432001f49Smrg glEnable(GL_DEPTH_TEST); 31532001f49Smrg glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 31632001f49Smrg 31732001f49Smrg glColor3f(1, 1, 1); 31832001f49Smrg 31932001f49Smrg glPushMatrix(); 32032001f49Smrg if (h->Id == 0) 32132001f49Smrg glRotatef(h->Angle, 0, 1, -1); 32232001f49Smrg else if (h->Id == 1) 32332001f49Smrg glRotatef(-(h->Angle), 0, 1, -1); 32432001f49Smrg else if (h->Id == 2) 32532001f49Smrg glRotatef(h->Angle, 0, 1, 1); 32632001f49Smrg else if (h->Id == 3) 32732001f49Smrg glRotatef(-(h->Angle), 0, 1, 1); 32832001f49Smrg glBindTexture(GL_TEXTURE_2D, Textures[0]); 32932001f49Smrg glBegin(GL_POLYGON); 33032001f49Smrg glTexCoord2f(0, 0); glVertex3f(-1, -1, -1); 33132001f49Smrg glTexCoord2f(1, 0); glVertex3f(-1, 1, -1); 33232001f49Smrg glTexCoord2f(1, 1); glVertex3f(-1, 1, 1); 33332001f49Smrg glTexCoord2f(0, 1); glVertex3f(-1, -1, 1); 33432001f49Smrg glEnd(); 33532001f49Smrg glBegin(GL_POLYGON); 33632001f49Smrg glTexCoord2f(0, 0); glVertex3f(1, -1, -1); 33732001f49Smrg glTexCoord2f(1, 0); glVertex3f(1, 1, -1); 33832001f49Smrg glTexCoord2f(1, 1); glVertex3f(1, 1, 1); 33932001f49Smrg glTexCoord2f(0, 1); glVertex3f(1, -1, 1); 34032001f49Smrg glEnd(); 34132001f49Smrg 34232001f49Smrg glBindTexture(GL_TEXTURE_2D, Textures[1]); 34332001f49Smrg glBegin(GL_POLYGON); 34432001f49Smrg glTexCoord2f(0, 0); glVertex3f(-1, -1, -1); 34532001f49Smrg glTexCoord2f(1, 0); glVertex3f( 1, -1, -1); 34632001f49Smrg glTexCoord2f(1, 1); glVertex3f( 1, -1, 1); 34732001f49Smrg glTexCoord2f(0, 1); glVertex3f(-1, -1, 1); 34832001f49Smrg glEnd(); 34932001f49Smrg glBegin(GL_POLYGON); 35032001f49Smrg glTexCoord2f(0, 0); glVertex3f(-1, 1, -1); 35132001f49Smrg glTexCoord2f(1, 0); glVertex3f( 1, 1, -1); 35232001f49Smrg glTexCoord2f(1, 1); glVertex3f( 1, 1, 1); 35332001f49Smrg glTexCoord2f(0, 1); glVertex3f(-1, 1, 1); 35432001f49Smrg glEnd(); 35532001f49Smrg 35632001f49Smrg glBindTexture(GL_TEXTURE_2D, Textures[2]); 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 glBegin(GL_POLYGON); 36432001f49Smrg glTexCoord2f(0, 0); glVertex3f(-1, -1, 1); 36532001f49Smrg glTexCoord2f(1, 0); glVertex3f( 1, -1, 1); 36632001f49Smrg glTexCoord2f(1, 1); glVertex3f( 1, 1, 1); 36732001f49Smrg glTexCoord2f(0, 1); glVertex3f(-1, 1, 1); 36832001f49Smrg glEnd(); 36932001f49Smrg 37032001f49Smrg glPopMatrix(); 37132001f49Smrg 37232001f49Smrg glXSwapBuffers(h->Dpy, h->Win); 37332001f49Smrg 37432001f49Smrg if (!glXMakeCurrent(h->Dpy, None, NULL)) { 37532001f49Smrg Error(h->DisplayName, "glXMakeCurrent failed in Redraw"); 37632001f49Smrg } 37732001f49Smrg pthread_mutex_unlock(&h->drawMutex); 37832001f49Smrg} 37932001f49Smrg 38032001f49Smrgstatic void *threadRunner (void *arg) 38132001f49Smrg{ 38232001f49Smrg struct thread_init_arg *tia = (struct thread_init_arg *) arg; 38332001f49Smrg struct window *win; 38432001f49Smrg 38532001f49Smrg win = &Windows[tia->id]; 38632001f49Smrg 38732001f49Smrg while(!terminate) { 38832001f49Smrg usleep(1000); 38932001f49Smrg Redraw(win); 39032001f49Smrg } 39132001f49Smrg 39232001f49Smrg return NULL; 39332001f49Smrg} 39432001f49Smrg 39532001f49Smrgstatic void 39632001f49SmrgResize(struct window *h, unsigned int width, unsigned int height) 39732001f49Smrg{ 39832001f49Smrg pthread_mutex_lock(&h->drawMutex); 39932001f49Smrg 40032001f49Smrg if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) { 40132001f49Smrg Error(h->DisplayName, "glXMakeCurrent failed in Resize()"); 40232001f49Smrg pthread_mutex_unlock(&h->drawMutex); 40332001f49Smrg return; 40432001f49Smrg } 40532001f49Smrg 40632001f49Smrg glViewport(0, 0, width, height); 40732001f49Smrg glMatrixMode(GL_PROJECTION); 40832001f49Smrg glLoadIdentity(); 40932001f49Smrg glFrustum(-1, 1, -1, 1, 2, 10); 41032001f49Smrg glMatrixMode(GL_MODELVIEW); 41132001f49Smrg glLoadIdentity(); 41232001f49Smrg glTranslatef(0, 0, -4.5); 41332001f49Smrg if (!glXMakeCurrent(h->Dpy, None, NULL)) { 41432001f49Smrg Error(h->DisplayName, "glXMakeCurrent failed in Resize()"); 41532001f49Smrg } 41632001f49Smrg pthread_mutex_unlock(&h->drawMutex); 41732001f49Smrg} 41832001f49Smrg 41932001f49Smrg 42032001f49Smrgstatic void 42132001f49SmrgEventLoop(void) 42232001f49Smrg{ 42332001f49Smrg while (1) { 42432001f49Smrg int i; 42532001f49Smrg XEvent event; 4267ec3b29aSmrg 4277ec3b29aSmrg /* Do we have an event? */ 4287ec3b29aSmrg if (XPending(gDpy) == 0) { 4297ec3b29aSmrg usleep(10000); 4307ec3b29aSmrg continue; 4317ec3b29aSmrg } 4327ec3b29aSmrg 43332001f49Smrg XNextEvent(gDpy, &event); 43432001f49Smrg for (i = 0; i < NumWindows; i++) { 43532001f49Smrg struct window *h = &Windows[i]; 43632001f49Smrg if (event.xany.window == h->Win) { 43732001f49Smrg switch (event.type) { 43832001f49Smrg case Expose: 43932001f49Smrg Redraw(h); 44032001f49Smrg break; 44132001f49Smrg case ConfigureNotify: 44232001f49Smrg Resize(h, event.xconfigure.width, event.xconfigure.height); 44332001f49Smrg break; 44432001f49Smrg case KeyPress: 44532001f49Smrg terminate = 1; 44632001f49Smrg return; 44732001f49Smrg default: 44832001f49Smrg /*no-op*/ ; 44932001f49Smrg } 45032001f49Smrg } 45132001f49Smrg } 45232001f49Smrg } 45332001f49Smrg} 45432001f49Smrg 45532001f49Smrgint 45632001f49Smrgmain(int argc, char *argv[]) 45732001f49Smrg{ 45832001f49Smrg const char *dpyName = XDisplayName(NULL); 45932001f49Smrg pthread_t t0, t1, t2, t3; 46032001f49Smrg struct thread_init_arg tia0, tia1, tia2, tia3; 46132001f49Smrg struct window *h0; 46232001f49Smrg 46332001f49Smrg XInitThreads(); 46432001f49Smrg 46532001f49Smrg gDpy = XOpenDisplay(dpyName); 46632001f49Smrg if (!gDpy) { 46732001f49Smrg Error(dpyName, "Unable to open display"); 46832001f49Smrg return -1; 46932001f49Smrg } 47032001f49Smrg 47132001f49Smrg if (initMainthread(gDpy, dpyName)) 47232001f49Smrg return -1; 47332001f49Smrg 47432001f49Smrg /* four windows and contexts sharing display lists and texture objects */ 47532001f49Smrg h0 = AddWindow(gDpy, dpyName, 10, 10, gCtx); 47632001f49Smrg (void) AddWindow(gDpy, dpyName, 330, 10, gCtx); 47732001f49Smrg (void) AddWindow(gDpy, dpyName, 10, 350, gCtx); 47832001f49Smrg (void) AddWindow(gDpy, dpyName, 330, 350, gCtx); 47932001f49Smrg 48032001f49Smrg if (!glXMakeCurrent(gDpy, h0->Win, gCtx)) { 48132001f49Smrg Error(dpyName, "glXMakeCurrent failed for init thread."); 48232001f49Smrg return -1; 48332001f49Smrg } 48432001f49Smrg 48532001f49Smrg InitGLstuff(); 48632001f49Smrg 48732001f49Smrg tia0.id = 0; 48832001f49Smrg pthread_create(&t0, NULL, threadRunner, &tia0); 48932001f49Smrg tia1.id = 1; 49032001f49Smrg pthread_create(&t1, NULL, threadRunner, &tia1); 49132001f49Smrg tia2.id = 2; 49232001f49Smrg pthread_create(&t2, NULL, threadRunner, &tia2); 49332001f49Smrg tia3.id = 3; 49432001f49Smrg pthread_create(&t3, NULL, threadRunner, &tia3); 49532001f49Smrg EventLoop(); 49632001f49Smrg return 0; 49732001f49Smrg} 498