132001f49Smrg/* 232001f49Smrg * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. 332001f49Smrg * 432001f49Smrg * Permission is hereby granted, free of charge, to any person obtaining a 532001f49Smrg * copy of this software and associated documentation files (the "Software"), 632001f49Smrg * to deal in the Software without restriction, including without limitation 732001f49Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 832001f49Smrg * and/or sell copies of the Software, and to permit persons to whom the 932001f49Smrg * Software is furnished to do so, subject to the following conditions: 1032001f49Smrg * 1132001f49Smrg * The above copyright notice and this permission notice shall be included 1232001f49Smrg * in all copies or substantial portions of the Software. 1332001f49Smrg * 1432001f49Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 1532001f49Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1632001f49Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1732001f49Smrg * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 1832001f49Smrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 1932001f49Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2032001f49Smrg */ 2132001f49Smrg 2232001f49Smrg/** 2332001f49Smrg * \file glxgears_fbconfig.c 2432001f49Smrg * Yet-another-version of gears. Originally ported to GLX by Brian Paul on 2532001f49Smrg * 23 March 2001. Modified to use fbconfigs by Ian Romanick on 10 Feb 2004. 2632001f49Smrg * 2732001f49Smrg * Command line options: 2832001f49Smrg * -info print GL implementation information 2932001f49Smrg * 3032001f49Smrg * \author Brian Paul 3132001f49Smrg * \author Ian Romanick <idr@us.ibm.com> 3232001f49Smrg */ 3332001f49Smrg 3432001f49Smrg 3532001f49Smrg#define GLX_GLXEXT_PROTOTYPES 3632001f49Smrg 3732001f49Smrg#include <math.h> 3832001f49Smrg#include <stdlib.h> 3932001f49Smrg#include <stdio.h> 4032001f49Smrg#include <string.h> 4132001f49Smrg#include <X11/Xlib.h> 4232001f49Smrg#include <X11/keysym.h> 4332001f49Smrg#include <GL/gl.h> 4432001f49Smrg#include <GL/glx.h> 4532001f49Smrg#include <GL/glxext.h> 4632001f49Smrg#include <assert.h> 4732001f49Smrg#include "pbutil.h" 4832001f49Smrg 4932001f49Smrgstatic PFNGLXCHOOSEFBCONFIGPROC choose_fbconfig = NULL; 5032001f49Smrgstatic PFNGLXGETVISUALFROMFBCONFIGPROC get_visual_from_fbconfig = NULL; 5132001f49Smrgstatic PFNGLXCREATENEWCONTEXTPROC create_new_context = NULL; 5232001f49Smrgstatic PFNGLXCREATEWINDOWPROC create_window = NULL; 5332001f49Smrgstatic PFNGLXDESTROYWINDOWPROC destroy_window = NULL; 5432001f49Smrg 5532001f49Smrg#define BENCHMARK 5632001f49Smrg 5732001f49Smrg#ifdef BENCHMARK 5832001f49Smrg 5932001f49Smrg/* XXX this probably isn't very portable */ 6032001f49Smrg 6132001f49Smrg#include <sys/time.h> 6232001f49Smrg#include <unistd.h> 6332001f49Smrg 6432001f49Smrg/* return current time (in seconds) */ 6532001f49Smrgstatic int 6632001f49Smrgcurrent_time(void) 6732001f49Smrg{ 6832001f49Smrg struct timeval tv; 6932001f49Smrg#ifdef __VMS 7032001f49Smrg (void) gettimeofday(&tv, NULL ); 7132001f49Smrg#else 7232001f49Smrg struct timezone tz; 7332001f49Smrg (void) gettimeofday(&tv, &tz); 7432001f49Smrg#endif 7532001f49Smrg return (int) tv.tv_sec; 7632001f49Smrg} 7732001f49Smrg 7832001f49Smrg#else /*BENCHMARK*/ 7932001f49Smrg 8032001f49Smrg/* dummy */ 8132001f49Smrgstatic int 8232001f49Smrgcurrent_time(void) 8332001f49Smrg{ 8432001f49Smrg return 0; 8532001f49Smrg} 8632001f49Smrg 8732001f49Smrg#endif /*BENCHMARK*/ 8832001f49Smrg 8932001f49Smrg 9032001f49Smrg 9132001f49Smrg#ifndef M_PI 9232001f49Smrg#define M_PI 3.14159265 9332001f49Smrg#endif 9432001f49Smrg 9532001f49Smrg 9632001f49Smrgstatic GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0; 9732001f49Smrgstatic GLint gear1, gear2, gear3; 9832001f49Smrgstatic GLfloat angle = 0.0; 9932001f49Smrg 10032001f49Smrg 10132001f49Smrg/* 10232001f49Smrg * 10332001f49Smrg * Draw a gear wheel. You'll probably want to call this function when 10432001f49Smrg * building a display list since we do a lot of trig here. 10532001f49Smrg * 10632001f49Smrg * Input: inner_radius - radius of hole at center 10732001f49Smrg * outer_radius - radius at center of teeth 10832001f49Smrg * width - width of gear 10932001f49Smrg * teeth - number of teeth 11032001f49Smrg * tooth_depth - depth of tooth 11132001f49Smrg */ 11232001f49Smrgstatic void 11332001f49Smrggear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, 11432001f49Smrg GLint teeth, GLfloat tooth_depth) 11532001f49Smrg{ 11632001f49Smrg GLint i; 11732001f49Smrg GLfloat r0, r1, r2; 11832001f49Smrg GLfloat angle, da; 11932001f49Smrg GLfloat u, v, len; 12032001f49Smrg 12132001f49Smrg r0 = inner_radius; 12232001f49Smrg r1 = outer_radius - tooth_depth / 2.0; 12332001f49Smrg r2 = outer_radius + tooth_depth / 2.0; 12432001f49Smrg 12532001f49Smrg da = 2.0 * M_PI / teeth / 4.0; 12632001f49Smrg 12732001f49Smrg glShadeModel(GL_FLAT); 12832001f49Smrg 12932001f49Smrg glNormal3f(0.0, 0.0, 1.0); 13032001f49Smrg 13132001f49Smrg /* draw front face */ 13232001f49Smrg glBegin(GL_QUAD_STRIP); 13332001f49Smrg for (i = 0; i <= teeth; i++) { 13432001f49Smrg angle = i * 2.0 * M_PI / teeth; 13532001f49Smrg glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); 13632001f49Smrg glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); 13732001f49Smrg if (i < teeth) { 13832001f49Smrg glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); 13932001f49Smrg glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), 14032001f49Smrg width * 0.5); 14132001f49Smrg } 14232001f49Smrg } 14332001f49Smrg glEnd(); 14432001f49Smrg 14532001f49Smrg /* draw front sides of teeth */ 14632001f49Smrg glBegin(GL_QUADS); 14732001f49Smrg da = 2.0 * M_PI / teeth / 4.0; 14832001f49Smrg for (i = 0; i < teeth; i++) { 14932001f49Smrg angle = i * 2.0 * M_PI / teeth; 15032001f49Smrg 15132001f49Smrg glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); 15232001f49Smrg glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); 15332001f49Smrg glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), 15432001f49Smrg width * 0.5); 15532001f49Smrg glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), 15632001f49Smrg width * 0.5); 15732001f49Smrg } 15832001f49Smrg glEnd(); 15932001f49Smrg 16032001f49Smrg glNormal3f(0.0, 0.0, -1.0); 16132001f49Smrg 16232001f49Smrg /* draw back face */ 16332001f49Smrg glBegin(GL_QUAD_STRIP); 16432001f49Smrg for (i = 0; i <= teeth; i++) { 16532001f49Smrg angle = i * 2.0 * M_PI / teeth; 16632001f49Smrg glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); 16732001f49Smrg glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); 16832001f49Smrg if (i < teeth) { 16932001f49Smrg glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), 17032001f49Smrg -width * 0.5); 17132001f49Smrg glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); 17232001f49Smrg } 17332001f49Smrg } 17432001f49Smrg glEnd(); 17532001f49Smrg 17632001f49Smrg /* draw back sides of teeth */ 17732001f49Smrg glBegin(GL_QUADS); 17832001f49Smrg da = 2.0 * M_PI / teeth / 4.0; 17932001f49Smrg for (i = 0; i < teeth; i++) { 18032001f49Smrg angle = i * 2.0 * M_PI / teeth; 18132001f49Smrg 18232001f49Smrg glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), 18332001f49Smrg -width * 0.5); 18432001f49Smrg glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), 18532001f49Smrg -width * 0.5); 18632001f49Smrg glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); 18732001f49Smrg glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); 18832001f49Smrg } 18932001f49Smrg glEnd(); 19032001f49Smrg 19132001f49Smrg /* draw outward faces of teeth */ 19232001f49Smrg glBegin(GL_QUAD_STRIP); 19332001f49Smrg for (i = 0; i < teeth; i++) { 19432001f49Smrg angle = i * 2.0 * M_PI / teeth; 19532001f49Smrg 19632001f49Smrg glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); 19732001f49Smrg glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); 19832001f49Smrg u = r2 * cos(angle + da) - r1 * cos(angle); 19932001f49Smrg v = r2 * sin(angle + da) - r1 * sin(angle); 20032001f49Smrg len = sqrt(u * u + v * v); 20132001f49Smrg u /= len; 20232001f49Smrg v /= len; 20332001f49Smrg glNormal3f(v, -u, 0.0); 20432001f49Smrg glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); 20532001f49Smrg glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); 20632001f49Smrg glNormal3f(cos(angle), sin(angle), 0.0); 20732001f49Smrg glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), 20832001f49Smrg width * 0.5); 20932001f49Smrg glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), 21032001f49Smrg -width * 0.5); 21132001f49Smrg u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da); 21232001f49Smrg v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da); 21332001f49Smrg glNormal3f(v, -u, 0.0); 21432001f49Smrg glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), 21532001f49Smrg width * 0.5); 21632001f49Smrg glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), 21732001f49Smrg -width * 0.5); 21832001f49Smrg glNormal3f(cos(angle), sin(angle), 0.0); 21932001f49Smrg } 22032001f49Smrg 22132001f49Smrg glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5); 22232001f49Smrg glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5); 22332001f49Smrg 22432001f49Smrg glEnd(); 22532001f49Smrg 22632001f49Smrg glShadeModel(GL_SMOOTH); 22732001f49Smrg 22832001f49Smrg /* draw inside radius cylinder */ 22932001f49Smrg glBegin(GL_QUAD_STRIP); 23032001f49Smrg for (i = 0; i <= teeth; i++) { 23132001f49Smrg angle = i * 2.0 * M_PI / teeth; 23232001f49Smrg glNormal3f(-cos(angle), -sin(angle), 0.0); 23332001f49Smrg glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); 23432001f49Smrg glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); 23532001f49Smrg } 23632001f49Smrg glEnd(); 23732001f49Smrg} 23832001f49Smrg 23932001f49Smrg 24032001f49Smrgstatic void 24132001f49Smrgdraw(void) 24232001f49Smrg{ 24332001f49Smrg glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 24432001f49Smrg 24532001f49Smrg glPushMatrix(); 24632001f49Smrg glRotatef(view_rotx, 1.0, 0.0, 0.0); 24732001f49Smrg glRotatef(view_roty, 0.0, 1.0, 0.0); 24832001f49Smrg glRotatef(view_rotz, 0.0, 0.0, 1.0); 24932001f49Smrg 25032001f49Smrg glPushMatrix(); 25132001f49Smrg glTranslatef(-3.0, -2.0, 0.0); 25232001f49Smrg glRotatef(angle, 0.0, 0.0, 1.0); 25332001f49Smrg glCallList(gear1); 25432001f49Smrg glPopMatrix(); 25532001f49Smrg 25632001f49Smrg glPushMatrix(); 25732001f49Smrg glTranslatef(3.1, -2.0, 0.0); 25832001f49Smrg glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0); 25932001f49Smrg glCallList(gear2); 26032001f49Smrg glPopMatrix(); 26132001f49Smrg 26232001f49Smrg glPushMatrix(); 26332001f49Smrg glTranslatef(-3.1, 4.2, 0.0); 26432001f49Smrg glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0); 26532001f49Smrg glCallList(gear3); 26632001f49Smrg glPopMatrix(); 26732001f49Smrg 26832001f49Smrg glPopMatrix(); 26932001f49Smrg} 27032001f49Smrg 27132001f49Smrg 27232001f49Smrg/* new window size or exposure */ 27332001f49Smrgstatic void 27432001f49Smrgreshape(int width, int height) 27532001f49Smrg{ 27632001f49Smrg GLfloat h = (GLfloat) height / (GLfloat) width; 27732001f49Smrg 27832001f49Smrg glViewport(0, 0, (GLint) width, (GLint) height); 27932001f49Smrg glMatrixMode(GL_PROJECTION); 28032001f49Smrg glLoadIdentity(); 28132001f49Smrg glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0); 28232001f49Smrg glMatrixMode(GL_MODELVIEW); 28332001f49Smrg glLoadIdentity(); 28432001f49Smrg glTranslatef(0.0, 0.0, -40.0); 28532001f49Smrg} 28632001f49Smrg 28732001f49Smrg 28832001f49Smrgstatic void 28932001f49Smrginit(void) 29032001f49Smrg{ 29132001f49Smrg static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 }; 29232001f49Smrg static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 }; 29332001f49Smrg static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 }; 29432001f49Smrg static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 }; 29532001f49Smrg 29632001f49Smrg glLightfv(GL_LIGHT0, GL_POSITION, pos); 29732001f49Smrg glEnable(GL_CULL_FACE); 29832001f49Smrg glEnable(GL_LIGHTING); 29932001f49Smrg glEnable(GL_LIGHT0); 30032001f49Smrg glEnable(GL_DEPTH_TEST); 30132001f49Smrg 30232001f49Smrg /* make the gears */ 30332001f49Smrg gear1 = glGenLists(1); 30432001f49Smrg glNewList(gear1, GL_COMPILE); 30532001f49Smrg glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red); 30632001f49Smrg gear(1.0, 4.0, 1.0, 20, 0.7); 30732001f49Smrg glEndList(); 30832001f49Smrg 30932001f49Smrg gear2 = glGenLists(1); 31032001f49Smrg glNewList(gear2, GL_COMPILE); 31132001f49Smrg glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green); 31232001f49Smrg gear(0.5, 2.0, 2.0, 10, 0.7); 31332001f49Smrg glEndList(); 31432001f49Smrg 31532001f49Smrg gear3 = glGenLists(1); 31632001f49Smrg glNewList(gear3, GL_COMPILE); 31732001f49Smrg glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue); 31832001f49Smrg gear(1.3, 2.0, 0.5, 10, 0.7); 31932001f49Smrg glEndList(); 32032001f49Smrg 32132001f49Smrg glEnable(GL_NORMALIZE); 32232001f49Smrg} 32332001f49Smrg 32432001f49Smrg 32532001f49Smrgstatic GLXWindow 32632001f49Smrgdummy_create_window(Display *dpy, GLXFBConfig config, Window win, 32732001f49Smrg const int *attrib_list) 32832001f49Smrg{ 32932001f49Smrg (void) dpy; 33032001f49Smrg (void) config; 33132001f49Smrg (void) attrib_list; 33232001f49Smrg 33332001f49Smrg return (GLXWindow) win; 33432001f49Smrg} 33532001f49Smrg 33632001f49Smrg 33732001f49Smrgstatic void 33832001f49Smrgdummy_destroy_window(Display *dpy, GLXWindow win) 33932001f49Smrg{ 34032001f49Smrg (void) dpy; 34132001f49Smrg (void) win; 34232001f49Smrg} 34332001f49Smrg 34432001f49Smrg 34532001f49Smrg/** 34632001f49Smrg * Initialize fbconfig related function pointers. 34732001f49Smrg */ 34832001f49Smrgstatic void 34932001f49Smrginit_fbconfig_functions(Display *dpy, int scrnum) 35032001f49Smrg{ 35132001f49Smrg const char * glx_extensions; 35232001f49Smrg const char * match; 35332001f49Smrg static const char ext_name[] = "GLX_SGIX_fbconfig"; 35432001f49Smrg const size_t len = strlen( ext_name ); 35532001f49Smrg int major; 35632001f49Smrg int minor; 35732001f49Smrg GLboolean ext_version_supported; 35832001f49Smrg GLboolean glx_1_3_supported; 35932001f49Smrg 36032001f49Smrg 36132001f49Smrg /* Determine if GLX 1.3 or greater is supported. 36232001f49Smrg */ 36332001f49Smrg glXQueryVersion(dpy, & major, & minor); 36432001f49Smrg glx_1_3_supported = (major == 1) && (minor >= 3); 36532001f49Smrg 36632001f49Smrg /* Determine if GLX_SGIX_fbconfig is supported. 36732001f49Smrg */ 36832001f49Smrg glx_extensions = glXQueryExtensionsString(dpy, scrnum); 36932001f49Smrg match = strstr( glx_extensions, ext_name ); 37032001f49Smrg 37132001f49Smrg ext_version_supported = (match != NULL) 37232001f49Smrg && ((match[len] == '\0') || (match[len] == ' ')); 37332001f49Smrg 37432001f49Smrg printf( "GLX 1.3 is %ssupported.\n", 37532001f49Smrg (glx_1_3_supported) ? "" : "not " ); 37632001f49Smrg printf( "%s is %ssupported.\n", 37732001f49Smrg ext_name, (ext_version_supported) ? "" : "not " ); 37832001f49Smrg 37932001f49Smrg if ( glx_1_3_supported ) { 38032001f49Smrg choose_fbconfig = (PFNGLXCHOOSEFBCONFIGPROC) 38132001f49Smrg glXGetProcAddressARB((GLubyte *) "glXChooseFBConfig"); 38232001f49Smrg get_visual_from_fbconfig = (PFNGLXGETVISUALFROMFBCONFIGPROC) 38332001f49Smrg glXGetProcAddressARB((GLubyte *) "glXGetVisualFromFBConfig"); 38432001f49Smrg create_new_context = (PFNGLXCREATENEWCONTEXTPROC) 38532001f49Smrg glXGetProcAddressARB((GLubyte *) "glXCreateNewContext"); 38632001f49Smrg create_window = (PFNGLXCREATEWINDOWPROC) 38732001f49Smrg glXGetProcAddressARB((GLubyte *) "glXCreateWindow"); 38832001f49Smrg destroy_window = (PFNGLXDESTROYWINDOWPROC) 38932001f49Smrg glXGetProcAddressARB((GLubyte *) "glXDestroyWindow"); 39032001f49Smrg } 39132001f49Smrg else if ( ext_version_supported ) { 39232001f49Smrg choose_fbconfig = (PFNGLXCHOOSEFBCONFIGPROC) 39332001f49Smrg glXGetProcAddressARB((GLubyte *) "glXChooseFBConfigSGIX"); 39432001f49Smrg get_visual_from_fbconfig = (PFNGLXGETVISUALFROMFBCONFIGPROC) 39532001f49Smrg glXGetProcAddressARB((GLubyte *) "glXGetVisualFromFBConfigSGIX"); 39632001f49Smrg create_new_context = (PFNGLXCREATENEWCONTEXTPROC) 39732001f49Smrg glXGetProcAddressARB((GLubyte *) "glXCreateContextWithConfigSGIX"); 39832001f49Smrg create_window = dummy_create_window; 39932001f49Smrg destroy_window = dummy_destroy_window; 40032001f49Smrg } 40132001f49Smrg else { 40232001f49Smrg printf( "This demo requires either GLX 1.3 or %s be supported.\n", 40332001f49Smrg ext_name ); 40432001f49Smrg exit(1); 40532001f49Smrg } 40632001f49Smrg 40732001f49Smrg if ( choose_fbconfig == NULL ) { 40832001f49Smrg printf( "glXChooseFBConfig not found!\n" ); 40932001f49Smrg exit(1); 41032001f49Smrg } 41132001f49Smrg 41232001f49Smrg if ( get_visual_from_fbconfig == NULL ) { 41332001f49Smrg printf( "glXGetVisualFromFBConfig not found!\n" ); 41432001f49Smrg exit(1); 41532001f49Smrg } 41632001f49Smrg 41732001f49Smrg if ( create_new_context == NULL ) { 41832001f49Smrg printf( "glXCreateNewContext not found!\n" ); 41932001f49Smrg exit(1); 42032001f49Smrg } 42132001f49Smrg} 42232001f49Smrg 42332001f49Smrg 42432001f49Smrg/* 42532001f49Smrg * Create an RGB, double-buffered window. 42632001f49Smrg * Return the window and context handles. 42732001f49Smrg */ 42832001f49Smrgstatic void 42932001f49Smrgmake_window( Display *dpy, const char *name, 43032001f49Smrg int x, int y, int width, int height, 43132001f49Smrg Window *winRet, GLXWindow *glxWinRet, GLXContext *ctxRet) 43232001f49Smrg{ 43332001f49Smrg int attrib[] = { GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, 43432001f49Smrg GLX_RENDER_TYPE, GLX_RGBA_BIT, 43532001f49Smrg GLX_RED_SIZE, 1, 43632001f49Smrg GLX_GREEN_SIZE, 1, 43732001f49Smrg GLX_BLUE_SIZE, 1, 43832001f49Smrg GLX_DOUBLEBUFFER, GL_TRUE, 43932001f49Smrg GLX_DEPTH_SIZE, 1, 44032001f49Smrg None }; 44132001f49Smrg GLXFBConfig * fbconfig; 44232001f49Smrg int num_configs; 44332001f49Smrg int scrnum; 44432001f49Smrg int i; 44532001f49Smrg XSetWindowAttributes attr; 44632001f49Smrg unsigned long mask; 44732001f49Smrg Window root; 44832001f49Smrg Window win; 44932001f49Smrg GLXWindow glxWin; 45032001f49Smrg GLXContext ctx; 45132001f49Smrg XVisualInfo *visinfo; 45232001f49Smrg 45332001f49Smrg scrnum = DefaultScreen( dpy ); 45432001f49Smrg root = RootWindow( dpy, scrnum ); 45532001f49Smrg 45632001f49Smrg init_fbconfig_functions(dpy, scrnum); 45732001f49Smrg fbconfig = (*choose_fbconfig)(dpy, scrnum, attrib, & num_configs); 45832001f49Smrg if (fbconfig == NULL) { 45932001f49Smrg printf("Error: couldn't get an RGB, Double-buffered visual\n"); 46032001f49Smrg exit(1); 46132001f49Smrg } 46232001f49Smrg 46332001f49Smrg printf("\nThe following fbconfigs meet the requirements. The first one " 46432001f49Smrg "will be used.\n\n"); 46532001f49Smrg for ( i = 0 ; i < num_configs ; i++ ) { 46632001f49Smrg PrintFBConfigInfo(dpy, scrnum, fbconfig[i], GL_TRUE); 46732001f49Smrg } 46832001f49Smrg 46932001f49Smrg /* window attributes */ 47032001f49Smrg visinfo = (*get_visual_from_fbconfig)(dpy, fbconfig[0]); 47132001f49Smrg assert(visinfo != NULL); 47232001f49Smrg attr.background_pixel = 0; 47332001f49Smrg attr.border_pixel = 0; 47432001f49Smrg attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone); 47532001f49Smrg attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; 47632001f49Smrg mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; 47732001f49Smrg 47832001f49Smrg win = XCreateWindow( dpy, root, 0, 0, width, height, 47932001f49Smrg 0, visinfo->depth, InputOutput, 48032001f49Smrg visinfo->visual, mask, &attr ); 48132001f49Smrg 48232001f49Smrg /* set hints and properties */ 48332001f49Smrg { 48432001f49Smrg XSizeHints sizehints; 48532001f49Smrg sizehints.x = x; 48632001f49Smrg sizehints.y = y; 48732001f49Smrg sizehints.width = width; 48832001f49Smrg sizehints.height = height; 48932001f49Smrg sizehints.flags = USSize | USPosition; 49032001f49Smrg XSetNormalHints(dpy, win, &sizehints); 49132001f49Smrg XSetStandardProperties(dpy, win, name, name, 49232001f49Smrg None, (char **)NULL, 0, &sizehints); 49332001f49Smrg } 49432001f49Smrg 49532001f49Smrg glxWin = (*create_window)(dpy, fbconfig[0], win, NULL); 49632001f49Smrg 49732001f49Smrg ctx = (*create_new_context)(dpy, fbconfig[0], GLX_RGBA_TYPE, NULL, GL_TRUE); 49832001f49Smrg if (!ctx) { 49932001f49Smrg printf("Error: glXCreateNewContext failed\n"); 50032001f49Smrg exit(1); 50132001f49Smrg } 50232001f49Smrg 50332001f49Smrg XFree(fbconfig); 50432001f49Smrg 50532001f49Smrg *glxWinRet = glxWin; 50632001f49Smrg *winRet = win; 50732001f49Smrg *ctxRet = ctx; 50832001f49Smrg} 50932001f49Smrg 51032001f49Smrg 51132001f49Smrgstatic void 51232001f49Smrgevent_loop(Display *dpy, GLXWindow win) 51332001f49Smrg{ 51432001f49Smrg while (1) { 51532001f49Smrg while (XPending(dpy) > 0) { 51632001f49Smrg XEvent event; 51732001f49Smrg XNextEvent(dpy, &event); 51832001f49Smrg switch (event.type) { 51932001f49Smrg case Expose: 52032001f49Smrg /* we'll redraw below */ 52132001f49Smrg break; 52232001f49Smrg case ConfigureNotify: 52332001f49Smrg reshape(event.xconfigure.width, event.xconfigure.height); 52432001f49Smrg break; 52532001f49Smrg case KeyPress: 52632001f49Smrg { 52732001f49Smrg char buffer[10]; 52832001f49Smrg int code; 52932001f49Smrg code = XLookupKeysym(&event.xkey, 0); 53032001f49Smrg if (code == XK_Left) { 53132001f49Smrg view_roty += 5.0; 53232001f49Smrg } 53332001f49Smrg else if (code == XK_Right) { 53432001f49Smrg view_roty -= 5.0; 53532001f49Smrg } 53632001f49Smrg else if (code == XK_Up) { 53732001f49Smrg view_rotx += 5.0; 53832001f49Smrg } 53932001f49Smrg else if (code == XK_Down) { 54032001f49Smrg view_rotx -= 5.0; 54132001f49Smrg } 54232001f49Smrg else { 54332001f49Smrg XLookupString(&event.xkey, buffer, sizeof(buffer), 54432001f49Smrg NULL, NULL); 54532001f49Smrg if (buffer[0] == 27) { 54632001f49Smrg /* escape */ 54732001f49Smrg return; 54832001f49Smrg } 54932001f49Smrg } 55032001f49Smrg } 55132001f49Smrg } 55232001f49Smrg } 55332001f49Smrg 55432001f49Smrg /* next frame */ 55532001f49Smrg angle += 2.0; 55632001f49Smrg 55732001f49Smrg draw(); 55832001f49Smrg glXSwapBuffers(dpy, win); 55932001f49Smrg 56032001f49Smrg /* calc framerate */ 56132001f49Smrg { 56232001f49Smrg static int t0 = -1; 56332001f49Smrg static int frames = 0; 56432001f49Smrg int t = current_time(); 56532001f49Smrg 56632001f49Smrg if (t0 < 0) 56732001f49Smrg t0 = t; 56832001f49Smrg 56932001f49Smrg frames++; 57032001f49Smrg 57132001f49Smrg if (t - t0 >= 5.0) { 57232001f49Smrg GLfloat seconds = t - t0; 57332001f49Smrg GLfloat fps = frames / seconds; 57432001f49Smrg printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds, 57532001f49Smrg fps); 57632001f49Smrg fflush(stdout); 57732001f49Smrg t0 = t; 57832001f49Smrg frames = 0; 57932001f49Smrg } 58032001f49Smrg } 58132001f49Smrg } 58232001f49Smrg} 58332001f49Smrg 58432001f49Smrg 58532001f49Smrgint 58632001f49Smrgmain(int argc, char *argv[]) 58732001f49Smrg{ 58832001f49Smrg Display *dpy; 58932001f49Smrg Window win; 59032001f49Smrg GLXWindow glxWin; 59132001f49Smrg GLXContext ctx; 59232001f49Smrg const char *dpyName = NULL; 59332001f49Smrg GLboolean printInfo = GL_FALSE; 59432001f49Smrg int i; 59532001f49Smrg 59632001f49Smrg for (i = 1; i < argc; i++) { 59732001f49Smrg if (strcmp(argv[i], "-display") == 0) { 59832001f49Smrg dpyName = argv[i+1]; 59932001f49Smrg i++; 60032001f49Smrg } 60132001f49Smrg else if (strcmp(argv[i], "-info") == 0) { 60232001f49Smrg printInfo = GL_TRUE; 60332001f49Smrg } 60432001f49Smrg } 60532001f49Smrg 60632001f49Smrg dpy = XOpenDisplay(dpyName); 60732001f49Smrg if (!dpy) { 60832001f49Smrg printf("Error: couldn't open display %s\n", XDisplayName(dpyName)); 60932001f49Smrg return -1; 61032001f49Smrg } 61132001f49Smrg 61232001f49Smrg make_window(dpy, "glxgears", 0, 0, 300, 300, &win, &glxWin, &ctx); 61332001f49Smrg XMapWindow(dpy, win); 61432001f49Smrg glXMakeCurrent(dpy, glxWin, ctx); 61532001f49Smrg 61632001f49Smrg if (printInfo) { 61732001f49Smrg printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); 61832001f49Smrg printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION)); 61932001f49Smrg printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR)); 62032001f49Smrg printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS)); 62132001f49Smrg } 62232001f49Smrg 62332001f49Smrg init(); 62432001f49Smrg 62532001f49Smrg event_loop(dpy, glxWin); 62632001f49Smrg 62732001f49Smrg glXDestroyContext(dpy, ctx); 62832001f49Smrg destroy_window(dpy, glxWin); 62932001f49Smrg XDestroyWindow(dpy, win); 63032001f49Smrg XCloseDisplay(dpy); 63132001f49Smrg 63232001f49Smrg return 0; 63332001f49Smrg} 634