Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

glwin.c

Go to the documentation of this file.
00001 /*
00002  * glwin.c -- Simple self-contained code for opening an 
00003  *            OpenGL-capable display window with a double buffered 
00004  *            mono or stereoscopic visual, and for receiving
00005  *            and decoding window-system events from
00006  *            Spaceball/SpaceNavigator/Magellen 6DOF input devices.
00007  *
00008  *            This code is primarily meant for 2-D image display
00009  *            or for trivial 3-D rendering usage without any GLX/WGL 
00010  *            extensions that have to be enumerated prior to 
00011  *            window creation.
00012  *
00013  *            This file is part of the Tachyon ray tracer.
00014  *            John E. Stone - john.stone@gmail.com
00015  *
00016  * $Id: glwin.c,v 1.35 2021/12/21 23:23:42 johns Exp $
00017  */
00018  
00019 #include <stdio.h>
00020 #include <stdlib.h>
00021 #include <math.h>
00022 #include <string.h>
00023 #include "glwin.h"
00024 
00025 /* Support for compilation as part of VMD for interactive */
00026 /* ray tracing display.                                   */
00027 #if defined(VMDOPENGL)
00028 #define USEOPENGL
00029 #endif
00030 
00031 #if defined(USEOPENGL)
00032 
00033 /* The Linux OpenGL ABI 1.0 spec requires that that GL_GLEXT_PROTOTYPES be 
00034  * defined before including gl.h or glx.h for extensions in order to get 
00035  * prototypes:  http://oss.sgi.com/projects/ogl-sample/ABI/index.html
00036  */
00037 #define GL_GLEXT_PROTOTYPES   1
00038 #define GLX_GLXEXT_PROTOTYPES 1
00039 
00040 #if (defined(WIN32) || defined(_WIN64)) && defined(_MSC_VER)
00041 /*
00042  * Win32
00043  */
00044 #ifndef _WIN32_WINNT
00045 #define _WIN32_WINNT 0x0400     /* hack for definition of wheel event codes */
00046 #endif
00047 #include <windows.h>
00048 #include <winuser.h>            /* mouse wheel event codes */
00049 #include <GL/gl.h>
00050 /* 3DxWare driver */
00051 #if defined(VMDSPACEWARE) && (defined(WIN32) || defined(_WIN64))
00052 #define OS_WIN32 1
00053 #include "spwmacro.h"           /* Spaceware include files */
00054 #include "si.h"                 /* Spaceware include files */
00055 #endif
00056 #else
00057 /*
00058  * X11
00059  */
00060 #include <X11/Xlib.h>
00061 #include <X11/keysym.h>
00062 #include <X11/Xatom.h>
00063 
00064 #if defined(USEEGL)
00065 /* use EGL for window management */
00066 #include <EGL/egl.h>
00067 #else
00068 /* use GLX for window management */
00069 #include <GL/glx.h>
00070 #endif
00071 
00072 /* use full OpenGL */
00073 #include <GL/gl.h>
00074 #endif
00075 
00076 /*
00077  * Optionally enable advanced OpenGL shaders for HMD usage, etc.
00078  */
00079 #if defined(USEGLEXT)
00080 
00081 /* NOTE: you may have to get copies of the latest OpenGL extension headers
00082  * from the OpenGL web site if your Linux machine lacks them:
00083  *   http://oss.sgi.com/projects/ogl-sample/registry/
00084  */
00085 #if (defined(__linux) || defined(_MSC_VER))
00086 #include <GL/glext.h>
00087 #endif
00088 
00089 /* not needed with recent OSX 10.9 revs */
00090 #if 0 && defined(__APPLE__)
00091 #include <OpenGL/glext.h>
00092 #endif
00093 
00094 /* required for Win32 calling conventions to work correctly */
00095 #ifndef APIENTRY
00096 #define APIENTRY
00097 #endif
00098 #ifndef GLAPI
00099 #define GLAPI extern
00100 #endif
00101 
00102 #endif
00103 
00104 /* 
00105  * Spaceball/Magellan/SpaceNavigator handle data structures
00106  */
00107 
00108 /* Window system event handling data */
00109 typedef struct {
00110 #if (defined(WIN32) || defined(_WIN64)) && defined(_MSC_VER)
00111 #if defined(USESPACEWARE)
00112   /* 3DxWare driver */
00113   SiHdl sball;             
00114   SiSpwEvent spwevent;     
00115   SiGetEventData spwedata; 
00116 #else
00117   int foo;                 
00118 #endif
00119 #else
00120   /* Xlib ClientMessage-based driver */
00121   Display *dpy;
00122   Window drv_win;
00123   Window app_win;
00124   Atom ev_motion;
00125   Atom ev_button_press;
00126   Atom ev_button_release;
00127   Atom ev_command;
00128 #endif
00129 } spaceballhandle;
00130 
00131 
00132 /* Platform-independent Spaceball event record */
00133 typedef struct {
00134   int event;                 
00135   int rx;                    
00136   int ry;                    
00137   int rz;                    
00138   int tx;                    
00139   int ty;                    
00140   int tz;                    
00141   int buttons;               
00142   int period;                
00143 } spaceballevent;
00144 
00145 
00146 #if !(defined(WIN32) || defined(_WIN64))
00147 /* GLSL shader state */
00148 typedef struct {
00149   int isvalid;                      
00150   GLhandleARB ProgramObject;        
00151   GLhandleARB VertexShaderObject;   
00152   GLhandleARB FragmentShaderObject; 
00153   int lastshader;                   
00154 } glsl_shader;
00155 #endif
00156 
00157 /* struct to provide access to key GLSL shader routines */
00158 typedef struct {
00159   int oglmajor;         
00160   int oglminor;         
00161   int oglrelease;       
00163   int hasglshaderobjectsarb;
00164   int hasglvertexshaderarb;
00165   int hasglfragmentshaderarb;
00166   int hasglgeometryshader4arb;
00167   int hasglsampleshadingarb;
00168   int hasglshadinglangarb;
00169   int hasglfborendertarget;
00170   int hasgetvideosyncsgi;
00171 
00172 /* when extensions are found in the headers, we include them in the struct */
00173 #if defined(GL_ARB_shader_objects)
00174   /* GLSL fctn ptrs  */
00175   GLhandleARB (APIENTRY *p_glCreateShaderObjectARB)(GLenum shaderType);
00176   GLhandleARB (APIENTRY *p_glCreateProgramObjectARB)(void);
00177   void (APIENTRY *p_glUseProgramObjectARB)(GLhandleARB programObj);
00178   void (APIENTRY *p_glDetachObjectARB)(GLhandleARB containerObj, GLhandleARB attachedObj);
00179   void (APIENTRY *p_glGetInfoLogARB)(GLhandleARB obj,GLsizei maxLength, GLsizei *length, GLcharARB *infoLog);
00180   void (APIENTRY *p_glGetObjectParameterivARB)(GLhandleARB obj, GLenum pname, GLint *params);
00181   void (APIENTRY *p_glLinkProgramARB)(GLhandleARB programObj);
00182   void (APIENTRY *p_glDeleteObjectARB)(GLhandleARB obj);
00183   void (APIENTRY *p_glAttachObjectARB)(GLhandleARB containerObj, GLhandleARB obj);
00184   void (APIENTRY *p_glCompileShaderARB)(GLhandleARB shaderObj);
00185   void (APIENTRY *p_glShaderSourceARB)(GLhandleARB shaderObj, GLsizei count, const GLcharARB **strings, const GLint *length);
00186   GLint (APIENTRY *p_glGetUniformLocationARB)(GLhandleARB programObject, const GLcharARB *name);
00187   void (APIENTRY *p_glUniform1iARB)(GLint location, GLint v0);
00188   void (APIENTRY *p_glUniform1fvARB)(GLint location, GLsizei count, GLfloat *value);
00189   void (APIENTRY *p_glUniform2fvARB)(GLint location, GLsizei count, GLfloat *value);
00190   void (APIENTRY *p_glUniform3fvARB)(GLint location, GLsizei count, GLfloat *value);
00191   void (APIENTRY *p_glUniform4fvARB)(GLint location, GLsizei count, GLfloat *value);
00192 
00193   /* FBO and render target fctns */
00194   void (APIENTRY *p_glGenFramebuffers)(GLsizei n, GLuint * framebuffers);
00195   void (APIENTRY *p_glBindFramebuffer)(GLenum target, GLuint framebuffer); 
00196   void (APIENTRY *p_glGenRenderbuffers)(GLsizei n, GLuint * renderbuffers);
00197   void (APIENTRY *p_glBindRenderbuffer)(GLenum target, GLuint renderbuffer);
00198   void (APIENTRY *p_glRenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
00199   void (APIENTRY *p_glFramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
00200   void (APIENTRY *p_glFramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
00201   GLenum (APIENTRY *p_glCheckFramebufferStatus)(GLenum target);
00202   void (APIENTRY *p_glDeleteRenderbuffers)(GLsizei n, const GLuint * renderbuffers);
00203   void (APIENTRY *p_glDeleteFramebuffers)(GLsizei n, const GLuint * framebuffers);
00204   void (APIENTRY *p_glDrawBuffers)(GLsizei n, const GLenum *bufs);
00205 #endif
00206 
00207   /* SGI video sync query extension */
00208   int (APIENTRY *p_glXGetVideoSyncSGI)(GLuint *count);
00209 } glwin_ext_fctns;
00210 
00211 
00212 #if defined(GL_ARB_shader_objects)
00213 /* GLSL shader functions */
00214 #define GLCREATESHADEROBJECTARB   ext->p_glCreateShaderObjectARB
00215 #define GLCREATEPROGRAMOBJECTARB  ext->p_glCreateProgramObjectARB
00216 #define GLUSEPROGRAMOBJECTARB     ext->p_glUseProgramObjectARB
00217 #define GLDETACHOBJECTARB         ext->p_glDetachObjectARB
00218 #define GLGETINFOLOGARB           ext->p_glGetInfoLogARB
00219 #define GLGETOBJECTPARAMETERIVARB ext->p_glGetObjectParameterivARB
00220 #define GLLINKPROGRAMARB          ext->p_glLinkProgramARB
00221 #define GLDELETEOBJECTARB         ext->p_glDeleteObjectARB
00222 #define GLATTACHOBJECTARB         ext->p_glAttachObjectARB
00223 #define GLCOMPILESHADERARB        ext->p_glCompileShaderARB
00224 #define GLSHADERSOURCEARB         ext->p_glShaderSourceARB
00225 #define GLGETUNIFORMLOCATIONARB   ext->p_glGetUniformLocationARB
00226 #define GLUNIFORM1IARB            ext->p_glUniform1iARB
00227 #define GLUNIFORM1FVARB           ext->p_glUniform1fvARB
00228 #define GLUNIFORM2FVARB           ext->p_glUniform2fvARB
00229 #define GLUNIFORM3FVARB           ext->p_glUniform3fvARB
00230 #define GLUNIFORM4FVARB           ext->p_glUniform4fvARB
00231 
00232 /* FBO and render buffer management functions */
00233 #define GLGENFRAMEBUFFERS         ext->p_glGenFramebuffers
00234 #define GLBINDFRAMEBUFFER         ext->p_glBindFramebuffer
00235 #define GLGENRENDERBUFFERS        ext->p_glGenRenderbuffers
00236 #define GLBINDRENDERBUFFER        ext->p_glBindRenderbuffer
00237 #define GLRENDERBUFFERSTORAGE     ext->p_glRenderbufferStorage
00238 #define GLFRAMEBUFFERTEXTURE2D    ext->p_glFramebufferTexture2D
00239 #define GLFRAMEBUFFERRENDERBUFFER ext->p_glFramebufferRenderbuffer
00240 #define GLCHECKFRAMEBUFFERSTATUS  ext->p_glCheckFramebufferStatus
00241 #define GLDELETERENDERBUFFERS     ext->p_glDeleteRenderbuffers
00242 #define GLDELETEFRAMEBUFFERS      ext->p_glDeleteFramebuffers
00243 #define GLDRAWBUFFERS             ext->p_glDrawBuffers
00244 
00245 /* video sync extensions */
00246 #define GLXGETVIDEOSYNCSGI        ext->p_glXGetVideoSyncSGI
00247 #endif
00248 
00249 
00250 /* OS and windowing system-specific handle data */
00251 typedef struct {
00252 #if (defined(WIN32) || defined(_WIN64)) && defined(_MSC_VER)
00253   HWND hWnd;                 
00254   HDC hDC;                   
00255   HGLRC hRC;                 
00256   long scrwidth;             
00257   long scrheight;            
00258   long MouseFlags;           
00259 #else
00260   int scrnum;                
00261   Display *dpy;              
00262   Window root;               
00263   Window win;                
00264   Atom wmDeleteWindow;       
00265 #if defined(USEEGL)
00266   EGLDisplay egldpy;         
00267   EGLConfig  eglconf;        
00268   EGLSurface eglsurf;        
00269   EGLContext eglctx;         
00270 #else
00271   GLXContext ctx;            
00272 #endif
00273 #endif
00274 
00275   int havestencil;           
00276   int instereo;              
00278   int width;                 
00279   int height;                
00280   int xpos;                  
00281   int ypos;                  
00282   int mousex;                
00283   int mousey;                
00284   int evdev;                 
00285   int evval;                 
00286   char evkey;                
00288   int havefocus;             
00289   spaceballhandle *sball;    
00290   spaceballevent sballevent; 
00292   glwin_ext_fctns *ext;   
00293 } oglhandle;
00294 
00295 
00296 #if defined(USEOPENGL) && !defined(USEEGL) && !(defined(WIN32) || defined(_WIN64)) && !defined(_MSC_VER)
00297 static int glx_query_extension(Display *dpy, const char *extname) {
00298   char *ext;
00299   char *endext;
00300   if (!extname)
00301     return 0;
00302 
00303   /* check for GLX extensions too */
00304   ext = (char *) glXQueryExtensionsString(dpy, 0);
00305   if (ext != NULL) {
00306     endext = ext + strlen(ext);
00307     while (ext < endext) {
00308       size_t n = strcspn(ext, " ");
00309       if ((strlen(extname) == n) && (strncmp(extname, ext, n) == 0)) {
00310         return 1; /* extension is available */
00311         break;
00312       }
00313       ext += (n + 1);
00314     }
00315   }
00316 
00317   return 0; /* False, extension is not available */
00318 }
00319 #endif
00320 
00321 
00322 /* static helper routines for handling quaternions from HMDs */
00323 static void quat_rot_matrix(float *m, const float *q) {
00324   m[ 0] = 1.0f - 2.0f * (q[1] * q[1] + q[2] * q[2]);
00325   m[ 1] = 2.0f * (q[0] * q[1] - q[2] * q[3]);
00326   m[ 2] = 2.0f * (q[2] * q[0] + q[1] * q[3]);
00327   m[ 3] = 0.0f;
00328 
00329   m[ 4] = 2.0f * (q[0] * q[1] + q[2] * q[3]);
00330   m[ 5] = 1.0f - 2.0f * (q[2] * q[2] + q[0] * q[0]);
00331   m[ 6] = 2.0f * (q[1] * q[2] - q[0] * q[3]);
00332   m[ 7] = 0.0f;
00333 
00334   m[ 8] = 2.0f * (q[2] * q[0] - q[1] * q[3]);
00335   m[ 9] = 2.0f * (q[1] * q[2] + q[0] * q[3]);
00336   m[10] = 1.0f - 2.0f * (q[1] * q[1] + q[0] * q[0]);
00337   m[11] = 0.0f;
00338 
00339   m[12] = 0.0f;
00340   m[13] = 0.0f;
00341   m[14] = 0.0f;
00342   m[15] = 1.0f;
00343 }
00344 
00345 
00346 /* prevent vendor-specific header file clashes */
00347 typedef void (APIENTRY *glwin_fctnptr)(void);
00348 
00349 /* static helper to query GL fctn pointers */
00350 void * glwin_get_procaddress(const char * procname) {
00351   void *fctn = NULL;
00352   if (!procname)
00353     return NULL;
00354 
00355 #if defined(_MSC_VER)
00356   /* NOTE: wgl returns a context-dependent function pointer
00357    *       the function can only be called within the same wgl
00358    *       context in which it was generated.
00359    */
00360   fctn = (glwin_fctnptr) wglGetProcAddress((LPCSTR) procname);
00361 #else
00362 
00363 #if !defined(_MSC_VER) && !defined(__APPLE__)
00364   /* GLX 1.4 form found on commercial Unix systems that
00365    * don't bother providing the ARB extension version that Linux prefers.
00366    */
00367   fctn = glXGetProcAddressARB((const GLubyte *) procname);
00368 #if 0
00369   printf("GL fctn '%s' %s\n", procname, (fctn) ? "available" : "NULL");
00370 #endif
00371 #endif
00372 
00373 
00374 #if defined(GLX_ARB_get_proc_address)
00375   /* NOTE: GLX returns a context-independent function pointer that
00376    *       can be called anywhere, no special handling is required.
00377    *       This method is used on Linux
00378    */
00379   if (fctn == NULL) {
00380     fctn = glXGetProcAddressARB((const GLubyte *) procname);
00381 #if 0
00382     printf("GLARB fctn '%s' %s\n", procname, (fctn) ? "available" : "NULL");
00383 #endif
00384   }
00385 #endif
00386 #endif
00387 
00388 #if 0
00389   printf("GL fctn '%s' %s\n", procname, (fctn) ? "available" : "NULL");
00390 #endif
00391 
00392   return fctn;
00393 }
00394 
00395 
00396 /* static helper routine to init OpenGL ext fctn pointers to NULL */
00397 void glwin_init_exts(void * voidhandle) {
00398   oglhandle * handle = (oglhandle *) voidhandle;
00399   if (handle == NULL)
00400     return;
00401   glwin_ext_fctns *ext = handle->ext;
00402 
00403   /* clear everything to zeros, so all ptrs are NULL, */
00404   /* and all flags are false.                         */
00405   memset(ext, 0, sizeof(glwin_ext_fctns));
00406 
00407 #if defined(GL_ARB_shading_language_100)
00408   /* check for the OpenGL Shading Language extension */
00409   if (glwin_query_extension("GL_ARB_shading_language_100")) {
00410     ext->hasglshadinglangarb = 1;
00411   }
00412 #endif
00413 
00414 #if defined(GL_ARB_shader_objects)
00415   if (glwin_query_extension("GL_ARB_shader_objects")) {
00416     ext->p_glCreateShaderObjectARB = (GLhandleARB (APIENTRY *)(GLenum)) glwin_get_procaddress("glCreateShaderObjectARB");
00417     ext->p_glCreateProgramObjectARB = (GLhandleARB (APIENTRY *)(void)) glwin_get_procaddress("glCreateProgramObjectARB");
00418     ext->p_glUseProgramObjectARB = (void (APIENTRY *)(GLhandleARB)) glwin_get_procaddress("glUseProgramObjectARB");
00419     ext->p_glDetachObjectARB = (void (APIENTRY *)(GLhandleARB, GLhandleARB)) glwin_get_procaddress("glDetachObjectARB");
00420     ext->p_glGetInfoLogARB = (void (APIENTRY *)(GLhandleARB, GLsizei, GLsizei *, GLcharARB *)) glwin_get_procaddress("glGetInfoLogARB");
00421     ext->p_glGetObjectParameterivARB = (void (APIENTRY *)(GLhandleARB, GLenum, GLint *)) glwin_get_procaddress("glGetObjectParameterivARB");
00422     ext->p_glLinkProgramARB = (void (APIENTRY *)(GLhandleARB)) glwin_get_procaddress("glLinkProgramARB");
00423     ext->p_glDeleteObjectARB = (void (APIENTRY *)(GLhandleARB)) glwin_get_procaddress("glDeleteObjectARB");
00424     ext->p_glAttachObjectARB = (void (APIENTRY *)(GLhandleARB, GLhandleARB)) glwin_get_procaddress("glAttachObjectARB");
00425     ext->p_glCompileShaderARB = (void (APIENTRY *)(GLhandleARB)) glwin_get_procaddress("glCompileShaderARB");
00426     ext->p_glShaderSourceARB = (void (APIENTRY *)(GLhandleARB, GLsizei, const GLcharARB **, const GLint *)) glwin_get_procaddress("glShaderSourceARB");
00427     ext->p_glGetUniformLocationARB = (GLint (APIENTRY *)(GLhandleARB programObject, const GLcharARB *name)) glwin_get_procaddress("glGetUniformLocationARB");
00428     ext->p_glUniform1iARB = (void (APIENTRY *)(GLint location, GLint v0)) glwin_get_procaddress("glUniform1iARB");
00429     ext->p_glUniform1fvARB = (void (APIENTRY *)(GLint location, GLsizei count, GLfloat *value)) glwin_get_procaddress("glUniform1fvARB");
00430     ext->p_glUniform2fvARB = (void (APIENTRY *)(GLint location, GLsizei count, GLfloat *value)) glwin_get_procaddress("glUniform2fvARB");
00431     ext->p_glUniform3fvARB = (void (APIENTRY *)(GLint location, GLsizei count, GLfloat *value)) glwin_get_procaddress("glUniform3fvARB");
00432     ext->p_glUniform4fvARB = (void (APIENTRY *)(GLint location, GLsizei count, GLfloat *value)) glwin_get_procaddress("glUniform4fvARB");
00433 
00434     if (ext->p_glCreateShaderObjectARB != NULL && ext->p_glCreateProgramObjectARB != NULL &&
00435         ext->p_glUseProgramObjectARB != NULL && ext->p_glDetachObjectARB != NULL &&
00436         ext->p_glGetInfoLogARB != NULL && ext->p_glGetObjectParameterivARB != NULL &&
00437         ext->p_glLinkProgramARB != NULL && ext->p_glDeleteObjectARB != NULL &&
00438         ext->p_glAttachObjectARB != NULL && ext->p_glCompileShaderARB != NULL &&
00439         ext->p_glShaderSourceARB != NULL && ext->p_glGetUniformLocationARB != NULL &&
00440         ext->p_glUniform1iARB != NULL && ext->p_glUniform1fvARB != NULL &&
00441         ext->p_glUniform2fvARB != NULL && ext->p_glUniform3fvARB != NULL &&
00442         ext->p_glUniform4fvARB  != NULL) {
00443       ext->hasglshaderobjectsarb = 1;
00444     } 
00445   }
00446 #endif
00447 
00448 #if defined(GL_ARB_vertex_shader)
00449   if (glwin_query_extension("GL_ARB_vertex_shader")) {
00450     ext->hasglvertexshaderarb = 1;
00451   }
00452 #endif
00453 
00454 #if defined(GL_ARB_fragment_shader)
00455   if (glwin_query_extension("GL_ARB_fragment_shader")) {
00456     ext->hasglfragmentshaderarb = 1;
00457   }
00458 #endif
00459 
00460 #if defined(GL_ARB_geometry_shader4)
00461   if (glwin_query_extension("GL_ARB_geometry_shader4")) {
00462     ext->hasglgeometryshader4arb = 1;
00463   }
00464 #endif
00465 
00466   if (glwin_query_extension("GL_ARB_sample_shading")) {
00467     ext->hasglsampleshadingarb = 1;
00468   }
00469 
00470 #if defined(GL_ARB_framebuffer_object)
00471   /* routines for managing FBOs and render targets */
00472   ext->p_glGenFramebuffers = (void (APIENTRY *)(GLsizei n, GLuint * framebuffers)) glwin_get_procaddress("glGenFramebuffers");
00473   ext->p_glBindFramebuffer = (void (APIENTRY *)(GLenum target, GLuint framebuffer)) glwin_get_procaddress("glBindFramebuffer"); 
00474   ext->p_glGenRenderbuffers = (void (APIENTRY *)(GLsizei n, GLuint * renderbuffers)) glwin_get_procaddress("glGenRenderbuffers");
00475   ext->p_glBindRenderbuffer = (void (APIENTRY *)(GLenum target, GLuint renderbuffer)) glwin_get_procaddress("glBindRenderbuffer");
00476   ext->p_glRenderbufferStorage = (void (APIENTRY *)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)) glwin_get_procaddress("glRenderbufferStorage");
00477   ext->p_glFramebufferTexture2D = (void (APIENTRY *)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)) glwin_get_procaddress("glFramebufferTexture2D");
00478   ext->p_glFramebufferRenderbuffer = (void (APIENTRY *)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)) glwin_get_procaddress("glFramebufferRenderbuffer");
00479   ext->p_glCheckFramebufferStatus = (GLenum (APIENTRY *)(GLenum target)) glwin_get_procaddress("glCheckFramebufferStatus");
00480   ext->p_glDeleteRenderbuffers = (void (APIENTRY *)(GLsizei n, const GLuint * renderbuffers)) glwin_get_procaddress("glDeleteRenderbuffers");
00481   ext->p_glDeleteFramebuffers = (void (APIENTRY *)(GLsizei n, const GLuint * framebuffers)) glwin_get_procaddress("glDeleteFramebuffers");
00482   ext->p_glDrawBuffers = (void (APIENTRY *)(GLsizei n, const GLenum *bufs)) glwin_get_procaddress("glDrawBuffers");
00483 
00484   if (ext->p_glGenFramebuffers != NULL && 
00485       ext->p_glBindFramebuffer != NULL &&
00486       ext->p_glGenRenderbuffers != NULL &&
00487       ext->p_glBindRenderbuffer != NULL && 
00488       ext->p_glRenderbufferStorage != NULL &&
00489       ext->p_glFramebufferTexture2D != NULL &&
00490       ext->p_glFramebufferRenderbuffer != NULL &&
00491       ext->p_glCheckFramebufferStatus != NULL &&
00492       ext->p_glDeleteRenderbuffers != NULL &&
00493       ext->p_glDeleteFramebuffers != NULL &&
00494       ext->p_glDrawBuffers != NULL) {
00495     ext->hasglfborendertarget = 1;
00496   }
00497 #endif
00498 
00499 #if !(defined(WIN32) || defined(_WIN64))
00500   if (glx_query_extension(handle->dpy, "GLX_SGI_video_sync")) {
00501     ext->p_glXGetVideoSyncSGI = (int (APIENTRY *)(GLuint *count)) glwin_get_procaddress("glXGetVideoSyncSGI");
00502 
00503     if (ext->p_glXGetVideoSyncSGI != NULL)
00504       ext->hasgetvideosyncsgi = 1;
00505   }
00506 #endif
00507 
00508 }
00509 
00510 
00511 #if !(defined(WIN32) || defined(_WIN64)) && !defined(_MSC_VER)
00512 /*
00513  * X11 version 
00514  */
00515 
00516 /*
00517  * Spaceball event handling routines
00518  */
00519 #define SBALL_COMMAND_NONE                0
00520 #define SBALL_COMMAND_APP_WINDOW      27695
00521 #define SBALL_COMMAND_APP_SENSITIVITY 27696
00522 
00523 /* enable 3Dxware Spaceball / Magellan / SpaceNavigator events */
00524 static spaceballhandle * spaceball_attach(Display *dpy, Window win) {
00525   /* allocate and clear handle data structure */
00526   spaceballhandle *handle = (spaceballhandle *) calloc(1, sizeof(spaceballhandle));
00527 
00528   /* find and store X atoms for the event types we care about */
00529   handle->ev_motion         = XInternAtom(dpy, "MotionEvent", True);
00530   handle->ev_button_press   = XInternAtom(dpy, "ButtonPressEvent", True);
00531   handle->ev_button_release = XInternAtom(dpy, "ButtonReleaseEvent", True);
00532   handle->ev_command        = XInternAtom(dpy, "CommandEvent", True);
00533 
00534   if (!handle->ev_motion || !handle->ev_button_press ||
00535       !handle->ev_button_release || !handle->ev_command) {
00536     free(handle);
00537     return NULL; /* driver is not running */
00538   }
00539 
00540   /* Find the root window of the driver */
00541   Window root = RootWindow(dpy, DefaultScreen(dpy));
00542 
00543   /* Find the driver's window */
00544   Atom ActualType;
00545   int ActualFormat;
00546   unsigned long NItems, BytesReturn;
00547   unsigned char *PropReturn = NULL;
00548   XGetWindowProperty(dpy, root, handle->ev_command, 0, 1, 0,
00549                      AnyPropertyType, &ActualType, &ActualFormat, &NItems,
00550                      &BytesReturn, &PropReturn );
00551   if (PropReturn == NULL) {
00552     free(handle);
00553     return NULL;
00554   }
00555   handle->drv_win = *(Window *) PropReturn;
00556   XFree(PropReturn);
00557 
00558   XTextProperty sball_drv_winname;
00559   if (XGetWMName(dpy, handle->drv_win, &sball_drv_winname) != 0) {
00560     if (!strcmp("Magellan Window", (char *) sball_drv_winname.value)) {
00561       /* Send the application window to the Spaceball/Magellan driver */
00562       XEvent msg;
00563       msg.type = ClientMessage;
00564       msg.xclient.format = 16;
00565       msg.xclient.send_event = 0;
00566       msg.xclient.display = dpy;
00567       msg.xclient.window = handle->drv_win;
00568       msg.xclient.message_type = handle->ev_command;
00569 
00570       msg.xclient.data.s[0] = (short) (((win)>>16)&0x0000FFFF); /* High 16 */
00571       msg.xclient.data.s[1] = (short) (((win))    &0x0000FFFF); /* Low 16  */
00572       msg.xclient.data.s[2] = SBALL_COMMAND_APP_WINDOW;         /* 27695   */
00573 
00574       int rc = XSendEvent(dpy, handle->drv_win, 0, 0x0000, &msg);
00575       XFlush(dpy);
00576       if (rc == 0) {
00577         free(handle);
00578         return NULL;
00579       }
00580     }
00581 
00582     XFree(sball_drv_winname.value);
00583   }
00584 
00585   return handle;
00586 }
00587 
00588 
00589 static void spaceball_close(spaceballhandle *handle) {
00590   free(handle);
00591 }
00592 
00593 
00594 static int spaceball_decode_event(spaceballhandle *handle, const XEvent *xev, spaceballevent *sballevent) {
00595   unsigned int evtype;
00596 
00597   if (handle == NULL || xev == NULL || sballevent == NULL)
00598     return 0;
00599 
00600   if (xev->type != ClientMessage)
00601     return 0;
00602 
00603   evtype = xev->xclient.message_type;
00604   if (evtype == handle->ev_motion) {
00605     /* We add the current control inputs to whatever we had previously, */
00606     /* so that we can process all queued events and not drop any inputs */
00607     sballevent->tx     += xev->xclient.data.s[2];  /* X translation          */
00608     sballevent->ty     += xev->xclient.data.s[3];  /* Y translation          */
00609     sballevent->tz     += xev->xclient.data.s[4];  /* Z translation          */
00610     sballevent->rx     += xev->xclient.data.s[5];  /* A rotation             */
00611     sballevent->ry     += xev->xclient.data.s[6];  /* B rotation             */
00612     sballevent->rz     += xev->xclient.data.s[7];  /* C rotation             */
00613     sballevent->period += xev->xclient.data.s[8];  /* Period in milliseconds */
00614     sballevent->event = 1;
00615     return 1;
00616   } else if (evtype == handle->ev_button_press) {
00617     sballevent->buttons |= (1 << xev->xclient.data.s[2]);
00618     sballevent->event = 1;
00619     return 1;
00620   } else if (evtype == handle->ev_button_release) {
00621     sballevent->buttons &= ~(1 << xev->xclient.data.s[2]);
00622     sballevent->event = 1;
00623     return 1;
00624   }
00625 
00626   return 0;
00627 }
00628 
00629 
00630 static void spaceball_init_event(spaceballevent *sballevent) {
00631   memset(sballevent, 0, sizeof(spaceballevent));
00632 }
00633 
00634 
00635 static void spaceball_clear_event(spaceballevent *sballevent) {
00636   sballevent->tx = 0;
00637   sballevent->ty = 0;
00638   sballevent->tz = 0;
00639   sballevent->rx = 0;
00640   sballevent->ry = 0;
00641   sballevent->rz = 0;
00642   sballevent->period = 0;
00643   sballevent->event = 0;
00644 }
00645 
00646 
00647 static oglhandle *glwin_alloc_init(void) {
00648   oglhandle * handle = (oglhandle *) calloc(1, sizeof(oglhandle));
00649   if (handle == NULL)
00650     return NULL;
00651 
00652 #if defined(VMDOPENGL)
00653   /* If this code is compiled into VMD, we honor the VMD scheme for */
00654   /* directing the VMD graphics window to a particular display      */
00655   if (getenv("VMDGDISPLAY") != NULL) {
00656     handle->dpy = XOpenDisplay(getenv("VMDGDISPLAY"));
00657   } else {
00658     handle->dpy = XOpenDisplay(getenv("DISPLAY"));
00659   }
00660 #else
00661   handle->dpy = XOpenDisplay(getenv("DISPLAY"));
00662 #endif
00663   if (handle->dpy == NULL) {
00664     free(handle);
00665     return NULL;
00666   } 
00667 
00668   handle->scrnum = DefaultScreen(handle->dpy);
00669   handle->root = RootWindow(handle->dpy, handle->scrnum);
00670   handle->havestencil = 0;
00671   handle->instereo = 0;
00672   handle->evdev = GLWIN_EV_NONE;
00673   handle->havefocus = 0;
00674 
00675   handle->ext = (glwin_ext_fctns *) calloc(1, sizeof(glwin_ext_fctns));
00676 
00677   return handle;
00678 }
00679 
00680 
00681 /*
00682  * X11 implementation of glwin routines
00683  */
00684 void * glwin_create(const char * wintitle, int width, int height) {
00685 #if defined(USEEGL)
00686   /* EGL */
00687   oglhandle * handle; 
00688   XSetWindowAttributes attr;
00689   unsigned long mask;
00690   int num_visuals;
00691   XVisualInfo vistemplate;
00692   XVisualInfo *vis=NULL;
00693   XSizeHints sizeHints;
00694   GLint stencilbits;
00695   EGLint eglmaj, eglmin;
00696   EGLint num_config=0;
00697 
00698 #if defined(USEOPENGLES2)
00699 #define GLWIN_RENDERABLE_TYPE EGL_OPENGL_ES2_BIT
00700 #else
00701 #define GLWIN_RENDERABLE_TYPE EGL_OPENGL_BIT
00702 #endif
00703 
00704   EGLint eglnormalattrib[] =   { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, 
00705                                  EGL_BLUE_SIZE, 8, 
00706                                  EGL_DEPTH_SIZE, 16, 
00707                                  EGL_STENCIL_SIZE, 1,
00708 /*                                 EGL_NATIVE_RENDERABLE,  */
00709                                  EGL_RENDERABLE_TYPE, GLWIN_RENDERABLE_TYPE,
00710 /*                                 EGL_SURFACE_TYPE, EGL_WINDOW_BIT, */
00711                                  EGL_NONE };
00712   EGLint eglfailsafeattrib[] = { EGL_RED_SIZE, 1, EGL_GREEN_SIZE, 1, 
00713                                  EGL_BLUE_SIZE, 1, 
00714 /*                                 EGL_DEPTH_SIZE, 16,  */
00715 /*                                 EGL_NATIVE_RENDERABLE, */
00716                                  EGL_RENDERABLE_TYPE, GLWIN_RENDERABLE_TYPE,
00717 /*                                 EGL_SURFACE_TYPE, EGL_WINDOW_BIT, */
00718                                  EGL_NONE };
00719 
00720   handle = glwin_alloc_init();
00721   handle->width = width;
00722   handle->height = height;
00723 
00724   /* setup EGL state */
00725 #if 1
00726   handle->egldpy = eglGetDisplay(handle->dpy);
00727 #else
00728   handle->egldpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
00729 #endif
00730   if (handle->egldpy == EGL_NO_DISPLAY) {
00731     printf("glwin_create(): Failed to connect to EGL display\n"); 
00732     free(handle);
00733     return NULL;
00734   }
00735 
00736   if (eglInitialize(handle->egldpy, &eglmaj, &eglmin) == EGL_FALSE) {
00737     printf("glwin_create(): Failed to initialize EGL display connection\n"); 
00738     free(handle);
00739     return NULL;
00740 #if 1
00741   } else {
00742     printf("EGL init dpy version: %d.%d\n", eglmaj, eglmin);
00743 #endif
00744   }
00745 
00746   /* try for full stereo w/ features first */
00747   handle->havestencil = 1;
00748   handle->instereo = 0;
00749   if (eglChooseConfig(handle->egldpy, eglnormalattrib, &handle->eglconf, 1, &num_config) == EGL_FALSE) {
00750     printf("eglChooseConfig(1) %d configs\n", num_config);
00751     if (eglChooseConfig(handle->egldpy, eglfailsafeattrib, &handle->eglconf, 1, &num_config) == EGL_FALSE) {
00752       printf("Error: eglChooseConfig() failed\n");
00753       free(handle);
00754       return NULL;
00755     }
00756     handle->havestencil = 0;
00757   }
00758   printf("eglChooseConfig() %d configs\n", num_config);
00759 
00760 
00761   EGLint vid;
00762   if (eglGetConfigAttrib(handle->egldpy, handle->eglconf, EGL_NATIVE_VISUAL_ID, &vid) == EGL_FALSE) {
00763     printf("Error: eglGetConfigAttrib() failed\n");
00764     return NULL;
00765   }
00766 
00767   vistemplate.visualid = vid;
00768   vis = XGetVisualInfo(handle->dpy, VisualIDMask, &vistemplate, &num_visuals);
00769   if (vis == NULL) {
00770     printf("Error: failed to obtain EGL-compatible X visual...\n");
00771     free(handle);
00772     return NULL;
00773   }
00774 
00775 
00776 #if defined(USEOPENGLES2)
00777   /* bind to OpenGL API since some implementations don't do this by default */
00778   if (eglBindAPI(EGL_OPENGL_ES_API) == EGL_FALSE) {
00779     printf("Error: failed to bind OpenGL ES API\n");
00780     free(handle);
00781     return NULL;
00782   }
00783 #else
00784   /* bind to OpenGL API since some implementations don't do this by default */
00785   if (eglBindAPI(EGL_OPENGL_API) == EGL_FALSE) {
00786     printf("Error: failed to bind full OpenGL API\n");
00787     free(handle);
00788     return NULL;
00789   }
00790 #endif
00791 
00792 
00793   /* window attributes */
00794   attr.background_pixel = 0;
00795   attr.border_pixel = 0;
00796   attr.colormap = XCreateColormap(handle->dpy, handle->root, 
00797                                   vis->visual, AllocNone);
00798 
00799   attr.event_mask = StructureNotifyMask | ExposureMask;
00800   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
00801 
00802   handle->win = XCreateWindow(handle->dpy, handle->root, 0, 0, width, height,
00803                               0, vis->depth, InputOutput,
00804                               vis->visual, mask, &attr );
00805 
00806 #if 0
00807   /* XXX untested EWMH code to enable compositor bypass  */
00808   Atom bypasscomp = X11_XInternAtom(handle->dpy, "_NET_WM_BYPASS_COMPOSITOR", False);
00809   const long bypasscomp_on = 1;
00810   X11_XChangeProperty(handle->dpy, handle->win, bypasscomp, XA_CARDINAL, 32,
00811                       PropModeReplace, (unsigned char *) bypasscomp_on, 1);
00812 #endif
00813 
00814   handle->eglctx = eglCreateContext(handle->dpy, handle->eglconf, EGL_NO_CONTEXT, NULL);
00815 
00816   handle->eglsurf = eglCreateWindowSurface(handle->egldpy, handle->eglconf, handle->win, NULL);
00817   eglMakeCurrent(handle->dpy, handle->eglsurf, handle->eglsurf, handle->eglctx);
00818 
00819   /* initialize extensions once window has been made current... */
00820   glwin_init_exts(handle);
00821 
00822   EGLint Context_RendererType=0;
00823   eglQueryContext(handle->egldpy, handle->eglctx, EGL_CONTEXT_CLIENT_TYPE, &Context_RendererType);
00824 
00825   const char *glstring="uninitialized";
00826   char buf[1024];
00827   switch (Context_RendererType) {
00828     case    EGL_OPENGL_API: glstring = "OpenGL"; break;
00829     case EGL_OPENGL_ES_API: glstring = "OpenGL ES"; break;
00830     case    EGL_OPENVG_API: glstring = "OpenVG???"; break;
00831     default:
00832       sprintf(buf, "Unknown API: %x", Context_RendererType);
00833       glstring=buf; 
00834       break;
00835   }
00836   printf("EGL_CONTEXT_CLIENT_TYPE: %s\n", glstring);
00837 
00838 
00839   XStoreName(handle->dpy, handle->win, wintitle);
00840 
00841   XSelectInput(handle->dpy, handle->win,
00842                KeyPressMask | ButtonPressMask | ButtonReleaseMask |
00843                PointerMotionMask | StructureNotifyMask | ExposureMask |
00844                EnterWindowMask | LeaveWindowMask | FocusChangeMask);
00845 
00846   /* set window manager size and position hints */ 
00847   memset((void *) &(sizeHints), 0, sizeof(sizeHints));
00848   sizeHints.flags |= USSize;
00849   sizeHints.flags |= USPosition;
00850   sizeHints.width = width;
00851   sizeHints.height = height;
00852   sizeHints.x = 0;
00853   sizeHints.y = 0;
00854   XSetWMNormalHints(handle->dpy, handle->win, &sizeHints); 
00855 
00856   /* cause X11 to generate a ClientMessage event when the window manager */
00857   /* wants to close window, so we can gracefully exit rather than crash  */
00858   handle->wmDeleteWindow = XInternAtom(handle->dpy, "WM_DELETE_WINDOW", False);
00859   XSetWMProtocols(handle->dpy, handle->win, &handle->wmDeleteWindow, 1);
00860 
00861   XMapRaised(handle->dpy, handle->win);
00862 
00863   /* Enable Spaceball events to this window */
00864 #if 0
00865   /* do focus processing for ourselves      */
00866   handle->sball = spaceball_attach(handle->dpy, handle->win);
00867 #else
00868   /* driver will do focus processing for us */
00869   handle->sball = spaceball_attach(handle->dpy, InputFocus);
00870 #endif
00871   /* initialize spaceball event structure   */
00872   spaceball_init_event(&handle->sballevent);
00873   spaceball_clear_event(&handle->sballevent);
00874 
00875   glwin_handle_events(handle, GLWIN_EV_POLL_BLOCK);
00876 
00877 #if 0
00878   /* check for an OpenGL stencil buffer */
00879   glGetIntegerv(GL_STENCIL_BITS, &stencilbits);
00880   if (stencilbits > 0) {
00881     handle->havestencil = 1;
00882   }
00883 #endif
00884 
00885   glClearColor(1.0, 0.0, 0.0, 1.0);
00886   glClear(GL_COLOR_BUFFER_BIT);
00887   glwin_swap_buffers(handle);
00888   glClear(GL_COLOR_BUFFER_BIT);
00889   glwin_swap_buffers(handle);
00890 
00891 
00892   XFlush(handle->dpy);
00893 
00894   return handle;
00895 #else
00896   /* GLX */
00897   oglhandle * handle; 
00898   XSetWindowAttributes attr;
00899   unsigned long mask;
00900   XVisualInfo *vis=NULL;
00901   XSizeHints sizeHints;
00902   GLint stencilbits;
00903 
00904   int glxstereoattrib[] =   { GLX_RGBA, GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8,
00905                               GLX_BLUE_SIZE, 8, GLX_DEPTH_SIZE, 16, 
00906                               GLX_STENCIL_SIZE, 1,
00907                               GLX_STEREO, GLX_DOUBLEBUFFER, None };
00908   int glxnormalattrib[] =   { GLX_RGBA, GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, 
00909                               GLX_BLUE_SIZE, 8, GLX_DEPTH_SIZE, 16, 
00910                               GLX_STENCIL_SIZE, 1,
00911                               GLX_DOUBLEBUFFER, None };
00912   int glxfailsafeattrib[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, 
00913                               GLX_BLUE_SIZE, 1, GLX_DEPTH_SIZE, 16, 
00914                               GLX_DOUBLEBUFFER, None };
00915 
00916   handle = glwin_alloc_init();
00917   handle->width = width;
00918   handle->height = height;
00919 
00920   /* try for full stereo w/ features first */
00921   handle->havestencil = 1;
00922   handle->instereo = 1;
00923   vis=glXChooseVisual(handle->dpy, handle->scrnum, glxstereoattrib);
00924   if (vis == NULL) {
00925     handle->havestencil = 1;
00926     handle->instereo = 0;
00927     /* try non-stereo w/ full features next */
00928     vis=glXChooseVisual(handle->dpy, handle->scrnum, glxnormalattrib);
00929     if (vis == NULL) {
00930       handle->havestencil = 0;
00931       handle->instereo = 0;
00932       /* try minimal features last */
00933       vis=glXChooseVisual(handle->dpy, handle->scrnum, glxfailsafeattrib);
00934       if (vis == NULL) {
00935         free(handle);
00936         return NULL;
00937       }
00938     }
00939   }
00940 
00941   /* window attributes */
00942   attr.background_pixel = 0;
00943   attr.border_pixel = 0;
00944   attr.colormap = XCreateColormap(handle->dpy, handle->root, 
00945                                   vis->visual, AllocNone);
00946 
00947   attr.event_mask = StructureNotifyMask | ExposureMask;
00948   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
00949 
00950   handle->win = XCreateWindow(handle->dpy, handle->root, 0, 0, width, height,
00951                               0, vis->depth, InputOutput,
00952                               vis->visual, mask, &attr );
00953 
00954 #if 0
00955   /* XXX untested EWMH code to enable compositor bypass */
00956   Atom bypasscomp = X11_XInternAtom(handle->dpy, "_NET_WM_BYPASS_COMPOSITOR", False);
00957   const long bypasscomp_on = 1;
00958   X11_XChangeProperty(handle->dpy, handle->win, bypasscomp, XA_CARDINAL, 32,
00959                       PropModeReplace, (unsigned char *) bypasscomp_on, 1);
00960 #endif
00961 
00962   handle->ctx = glXCreateContext( handle->dpy, vis, NULL, True );
00963 
00964   glXMakeCurrent( handle->dpy, handle->win, handle->ctx );
00965 
00966   /* initialize extensions once window has been made current... */
00967   glwin_init_exts(handle);
00968 
00969   XStoreName(handle->dpy, handle->win, wintitle);
00970 
00971   XSelectInput(handle->dpy, handle->win,
00972                KeyPressMask | ButtonPressMask | ButtonReleaseMask |
00973                PointerMotionMask | StructureNotifyMask | ExposureMask |
00974                EnterWindowMask | LeaveWindowMask | FocusChangeMask);
00975 
00976   /* set window manager size and position hints */ 
00977   memset((void *) &(sizeHints), 0, sizeof(sizeHints));
00978   sizeHints.flags |= USSize;
00979   sizeHints.flags |= USPosition;
00980   sizeHints.width = width;
00981   sizeHints.height = height;
00982   sizeHints.x = 0;
00983   sizeHints.y = 0;
00984   XSetWMNormalHints(handle->dpy, handle->win, &sizeHints); 
00985 
00986   /* cause X11 to generate a ClientMessage event when the window manager */
00987   /* wants to close window, so we can gracefully exit rather than crash  */
00988   handle->wmDeleteWindow = XInternAtom(handle->dpy, "WM_DELETE_WINDOW", False);
00989   XSetWMProtocols(handle->dpy, handle->win, &handle->wmDeleteWindow, 1);
00990 
00991   XMapRaised(handle->dpy, handle->win);
00992 
00993   /* Enable Spaceball events to this window */
00994 #if 0
00995   /* do focus processing for ourselves      */
00996   handle->sball = spaceball_attach(handle->dpy, handle->win);
00997 #else
00998   /* driver will do focus processing for us */
00999   handle->sball = spaceball_attach(handle->dpy, InputFocus);
01000 #endif
01001   /* initialize spaceball event structure   */
01002   spaceball_init_event(&handle->sballevent);
01003   spaceball_clear_event(&handle->sballevent);
01004 
01005   glwin_handle_events(handle, GLWIN_EV_POLL_BLOCK);
01006 
01007   /* check for an OpenGL stencil buffer */
01008   glGetIntegerv(GL_STENCIL_BITS, &stencilbits);
01009   if (stencilbits > 0) {
01010     handle->havestencil = 1;
01011   }
01012 
01013   glClearColor(0.0, 0.0, 0.0, 1.0);
01014   glClear(GL_COLOR_BUFFER_BIT);
01015   glwin_swap_buffers(handle);
01016   glClear(GL_COLOR_BUFFER_BIT);
01017   glwin_swap_buffers(handle);
01018 
01019   XFlush(handle->dpy);
01020 
01021   return handle;
01022 #endif
01023 }
01024 
01025 
01026 void glwin_destroy(void * voidhandle) {
01027   oglhandle * handle = (oglhandle *) voidhandle;
01028   if (handle == NULL)
01029     return;
01030 
01031   /* detach spaceball        */
01032   if (handle->sball != NULL) {
01033     spaceball_close(handle->sball);
01034     handle->sball = NULL;
01035   }
01036 
01037   /* destroy GLSL and FBO extension fctns */
01038   if (handle->ext != NULL) {
01039     free(handle->ext);
01040   }
01041 
01042   /* close and delete window */
01043   XUnmapWindow(handle->dpy, handle->win);
01044 
01045 #if defined(USEEGL)
01046   /* EGL code path */
01047   eglMakeCurrent(handle->egldpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
01048   eglDestroyContext(handle->egldpy, handle->eglctx);
01049   eglDestroySurface(handle->egldpy, handle->eglsurf);
01050   eglTerminate(handle->egldpy);
01051 #else
01052   /* GLX code path */
01053   glXMakeCurrent(handle->dpy, None, NULL);
01054 #endif
01055 
01056   XDestroyWindow(handle->dpy, handle->win);
01057   XCloseDisplay(handle->dpy); 
01058 }
01059 
01060  
01061 void glwin_swap_buffers(void * voidhandle) {
01062   oglhandle * handle = (oglhandle *) voidhandle;
01063 
01064   if (handle != NULL)
01065 #if defined(USEEGL)
01066     /* EGL code path */
01067     eglSwapBuffers(handle->egldpy, handle->eglsurf);
01068 #else
01069     /* GLX code path */
01070     glXSwapBuffers(handle->dpy, handle->win);
01071 #endif
01072 }
01073 
01074 
01075 int glwin_handle_events(void * voidhandle, int evblockmode) {
01076   oglhandle * handle = (oglhandle *) voidhandle;
01077   int rc=0;
01078   char keybuf[10];
01079   int keybuflen = 9;
01080   KeySym keysym;
01081   XComposeStatus comp;
01082 
01083   if (handle == NULL)
01084     return 0;
01085 
01086   /* clear previous spaceball event state, except for button state which  */
01087   /* must be left alone.                                                  */
01088   spaceball_clear_event(&handle->sballevent);
01089 
01090 #if 0
01091   if (handle) { 
01092     /* check window size */
01093     XWindowAttributes xwa;
01094     XGetWindowAttributes(handle->dpy, handle->win, &xwa);
01095     handle->width = xwa.width;
01096     handle->height = xwa.height;
01097   }
01098 #endif
01099 
01100   /* only process a single recognized event and then return to the caller */
01101   /* otherwise it is too easy to drop mouse button press/release events   */
01102   while (!rc && (evblockmode || XPending(handle->dpy))) {
01103     int k; 
01104     unsigned int button;
01105     XEvent event;
01106 
01107     evblockmode = GLWIN_EV_POLL_NONBLOCK; /* subsequent loops don't block */
01108     XNextEvent(handle->dpy, &event);
01109     handle->evdev = GLWIN_EV_NONE;
01110     handle->evval = 0;
01111     handle->evkey = '\0';
01112 
01113     switch(event.type) {
01114       case Expose:
01115       case ReparentNotify:
01116       case MapNotify:
01117         rc=1; /* we got one event */
01118         break;
01119 
01120       case ConfigureNotify:
01121         handle->width = event.xconfigure.width;
01122         handle->height = event.xconfigure.height;
01123         handle->xpos = event.xconfigure.x;
01124         handle->ypos = event.xconfigure.y;
01125         rc=1; /* we got one event */
01126         break;
01127 
01128       case KeyPress:
01129         handle->mousex = event.xbutton.x;
01130         handle->mousey = event.xbutton.y;
01131         k = XLookupString(&(event.xkey), keybuf, keybuflen,  &keysym, &comp);
01132         if (k > 0 && keybuf[0] != '\0') {
01133           handle->evdev = GLWIN_EV_KBD;
01134           handle->evkey = keybuf[0];
01135           rc=1; /* we got one event */
01136         } else {
01137           handle->evdev = GLWIN_EV_NONE;
01138           handle->evkey = 0;
01139           switch (keysym) {
01140             case XK_Up:          handle->evdev = GLWIN_EV_KBD_UP;        break;
01141             case XK_Down:        handle->evdev = GLWIN_EV_KBD_DOWN;      break;
01142             case XK_Left:        handle->evdev = GLWIN_EV_KBD_LEFT;      break;
01143             case XK_Right:       handle->evdev = GLWIN_EV_KBD_RIGHT;     break;
01144             case XK_Page_Up:     handle->evdev = GLWIN_EV_KBD_PAGE_UP;   break;
01145             case XK_Page_Down:   handle->evdev = GLWIN_EV_KBD_PAGE_UP;   break;
01146             case XK_Home:        handle->evdev = GLWIN_EV_KBD_HOME;      break;
01147             case XK_End:         handle->evdev = GLWIN_EV_KBD_END;       break;
01148             case XK_Insert:      handle->evdev = GLWIN_EV_KBD_INSERT;    break;
01149             case XK_Delete:      handle->evdev = GLWIN_EV_KBD_DELETE;    break;
01150 
01151             case XK_F1:          handle->evdev = GLWIN_EV_KBD_F1;        break;
01152             case XK_F2:          handle->evdev = GLWIN_EV_KBD_F2;        break;
01153             case XK_F3:          handle->evdev = GLWIN_EV_KBD_F3;        break;
01154             case XK_F4:          handle->evdev = GLWIN_EV_KBD_F4;        break;
01155             case XK_F5:          handle->evdev = GLWIN_EV_KBD_F5;        break;
01156             case XK_F6:          handle->evdev = GLWIN_EV_KBD_F6;        break;
01157             case XK_F7:          handle->evdev = GLWIN_EV_KBD_F7;        break;
01158             case XK_F8:          handle->evdev = GLWIN_EV_KBD_F8;        break;
01159             case XK_F9:          handle->evdev = GLWIN_EV_KBD_F9;        break;
01160             case XK_F10:         handle->evdev = GLWIN_EV_KBD_F10;       break;
01161             case XK_F11:         handle->evdev = GLWIN_EV_KBD_F11;       break;
01162             case XK_F12:         handle->evdev = GLWIN_EV_KBD_F12;       break;
01163 
01164             case XK_Escape:      handle->evdev = GLWIN_EV_KBD_F12;       break;
01165           }
01166           if (handle->evdev != GLWIN_EV_NONE) 
01167             rc=1;
01168         }
01169         break;
01170 
01171       case MotionNotify:
01172         handle->evdev = GLWIN_EV_MOUSE_MOVE;
01173         handle->mousex = event.xmotion.x;
01174         handle->mousey = event.xmotion.y;
01175         rc=1; /* we got one event */
01176         break; 
01177 
01178       case ButtonPress:
01179       case ButtonRelease:
01180         button = event.xbutton.button;
01181         handle->evval = (event.type == ButtonPress);
01182         handle->mousex = event.xbutton.x;
01183         handle->mousey = event.xbutton.y;
01184         switch (button) {
01185           case Button1:
01186             handle->evdev = GLWIN_EV_MOUSE_LEFT;
01187             rc=1; /* we got one event */
01188             break;
01189           case Button2:
01190             handle->evdev = GLWIN_EV_MOUSE_MIDDLE;
01191             rc=1; /* we got one event */
01192             break;
01193           case Button3:
01194             handle->evdev = GLWIN_EV_MOUSE_RIGHT;
01195             rc=1; /* we got one event */
01196             break;
01197           case Button4:
01198             handle->evdev = GLWIN_EV_MOUSE_WHEELUP;
01199             rc=1; /* we got one event */
01200             break;
01201           case Button5:
01202             handle->evdev = GLWIN_EV_MOUSE_WHEELDOWN;
01203             rc=1; /* we got one event */
01204             break;
01205         }
01206         break;
01207 
01208       case FocusIn:
01209       case EnterNotify:
01210         handle->havefocus=1;
01211         break;
01212 
01213       case FocusOut:
01214       case LeaveNotify:
01215         handle->havefocus=0;
01216         break;
01217 
01218       case ClientMessage:
01219         /* handle window close events */
01220         if (event.xclient.data.l[0] == handle->wmDeleteWindow) {
01221           handle->evdev = GLWIN_EV_WINDOW_CLOSE;
01222           rc=1;
01223         } else {
01224 #if 1
01225           /* let the spaceball driver take care of focus processing           */
01226           /* if we have mouse/keyboard focus, then translate spaceball events */
01227           spaceball_decode_event(handle->sball, &event, &handle->sballevent);
01228 #else
01229           /* do our own focus handling                                        */
01230           /* if we have mouse/keyboard focus, then translate spaceball events */
01231           if (handle->havefocus) {
01232             spaceball_decode_event(handle->sball, &event, &handle->sballevent);
01233           }
01234 #endif
01235         } 
01236         break;
01237 
01238     } 
01239   }
01240 
01241   return rc;
01242 } 
01243 
01244 
01245 int glwin_resize(void *voidhandle, int width, int height) {
01246   oglhandle * handle = (oglhandle *) voidhandle;
01247   if (handle == NULL)
01248     return -1;
01249 
01250   XResizeWindow(handle->dpy, handle->win, width, height);
01251 
01252 #if 0
01253   XFlush(handle->dpy);
01254 #endif
01255 
01256   return 0;
01257 }
01258 
01259 
01260 int glwin_reposition(void *voidhandle, int xpos, int ypos) {
01261   oglhandle * handle = (oglhandle *) voidhandle;
01262   if (handle == NULL)
01263     return -1;
01264 
01265   XMoveWindow(handle->dpy, handle->win, xpos, ypos);
01266 
01267   return 0;
01268 }
01269 
01270 
01271 #if 0
01272 int glwin_switch_fullscreen_video_mode(void * voidhandle, mode...) {
01273   XF86VidModeSwitchToMode(display,defaultscreen,video_mode);
01274   XF86VidModeSetViewPort(display,DefaultScreen,0,0);
01275   XMoveResizeWindow(display,window,0,0,width,height);
01276   XMapRaised(display,window);
01277   XGrabPointer(display,window,True,0,GrabModeAsync,GrabModeAsync,window,0L,CurrentTime);
01278   XGrabKeyboard(display,window,False,GrabModeAsync,GrabModeAsync,CurrentTime);
01279 }
01280 #endif
01281 
01282 
01283 int glwin_fullscreen(void * voidhandle, int fson, int xinescreen) {
01284   struct {
01285     unsigned long flags;
01286     unsigned long functions;
01287     unsigned long decorations;
01288     long inputMode;
01289     unsigned long status;
01290   } wmhints;
01291   Atom wmproperty;
01292 
01293   oglhandle * handle = (oglhandle *) voidhandle;
01294 
01295   memset(&wmhints, 0, sizeof(wmhints));
01296   wmhints.flags = 2;         /* changing window decorations */
01297   if (fson) {
01298     wmhints.decorations = 0; /* 0 (false) no window decorations */
01299   } else {
01300     wmhints.decorations = 1; /* 1 (true) window decorations enabled */
01301   }
01302   wmproperty = XInternAtom(handle->dpy, "_MOTIF_WM_HINTS", True);
01303   XChangeProperty(handle->dpy, handle->win, wmproperty, wmproperty, 32,
01304                   PropModeReplace, (unsigned char *) &wmhints, 5);
01305 
01306 #if 0
01307   {
01308     XSetWindowAttributes xswa;
01309     xswa.override_redirect = False;
01310     XChangeWindowAttributes(handle->dpy, handle->win, CWOverrideRedirect, &xswa);
01311   }
01312 #endif
01313 
01314 #if 1 && defined(__linux)
01315   /* support EWMH methods for setting full-screen mode            */
01316   /* http://standards.freedesktop.org/wm-spec/wm-spec-latest.html */
01317   Atom fsatom = XInternAtom(handle->dpy, "_NET_WM_STATE_FULLSCREEN", True);
01318   Atom stateatom = XInternAtom(handle->dpy, "_NET_WM_STATE", True);
01319   if (fsatom != None && stateatom != None) {
01320 #if 0
01321     XChangeProperty(handle->dpy, handle->win, stateatom,
01322                     XA_ATOM, 32, PropModeReplace, (unsigned char*) &fsatom, 1);
01323 #endif
01324 
01325     XEvent xev;
01326     memset(&xev, 0, sizeof(xev));
01327     xev.type = ClientMessage;
01328     xev.xclient.window = handle->win;
01329     xev.xclient.message_type = stateatom;
01330     xev.xclient.format = 32;
01331     if (fson)
01332       xev.xclient.data.l[0] = 1; /* _NET_WM_STATE_ADD    */
01333     else 
01334       xev.xclient.data.l[0] = 0; /* _NET_WM_STATE_REMOVE */
01335     xev.xclient.data.l[1] = fsatom;
01336     xev.xclient.data.l[2] = 0;
01337 
01338     XSendEvent(handle->dpy, handle->root, False,
01339                SubstructureRedirectMask | SubstructureNotifyMask, &xev);
01340 
01341     XFlush(handle->dpy);
01342   } 
01343 #if 0
01344   else {
01345     printf("*** failed to obtain full screen X11 atom\n");
01346   }
01347 #endif
01348 #endif
01349 
01350   /* resize window to size of either the whole X display screen, */
01351   /* or to the size of one of the Xinerama component displays    */
01352   /* if Xinerama is enabled, and xinescreen is not -1.           */
01353   if (fson) {
01354     int dpyScreen = DefaultScreen(handle->dpy);
01355 
01356     XSizeHints sizeHints;
01357     memset((void *) &(sizeHints), 0, sizeof(sizeHints));
01358     sizeHints.flags |= USSize;
01359     sizeHints.flags |= USPosition;
01360 
01361     sizeHints.width = DisplayWidth(handle->dpy, dpyScreen);
01362     sizeHints.height = DisplayHeight(handle->dpy, dpyScreen);
01363     sizeHints.x = 0;
01364     sizeHints.y = 0;
01365 
01366 #if defined(USEXINERAMA)
01367     if (xinescreen != -1) {
01368       int xinerr, xinevent, xinenumscreens;
01369       if (XineramaQueryExtension(handle->dpy, &xinevent, &xinerr) &&
01370           XineramaIsActive(handle->dpy)) {
01371         XineramaScreenInfo *screens =
01372           XineramaQueryScreens(handle->dpy, &xinenumscreens);
01373         if (xinescreen >= 0 && xinescreen < xinenumscreens) {
01374           sizeHints.width = screens[xinescreen].width;
01375           sizeHints.height = screens[xinescreen].height;
01376           sizeHints.x = screens[xinescreen].x_org;
01377           sizeHints.y = screens[xinescreen].y_org;
01378 #if 1 || defined(DEBUGOUTPUT)
01379           printf("*** OpenGL Stereo: Xinerama screen %d, +%d+%dx%dx%d\n",
01380                  xinescreen, sizeHints.x, sizeHints.y,
01381                  sizeHints.width, sizeHints.height);
01382 #endif
01383         } else {
01384           printf("*** OpenGL Stereo: no such Xinerama screen index %d\n",
01385                  xinescreen);
01386         }
01387         XFree(screens);
01388       }
01389     }
01390 #endif
01391 
01392     XMoveWindow(handle->dpy, handle->win, sizeHints.x, sizeHints.y);
01393     XResizeWindow(handle->dpy, handle->win, sizeHints.width, sizeHints.height);
01394   }
01395 
01396 #if 0
01397   {
01398     XSetWindowAttributes xswa;
01399     xswa.override_redirect = True;
01400     XChangeWindowAttributes(handle->dpy, handle->win, CWOverrideRedirect, &xswa);
01401   }
01402 #endif
01403 
01404 #if 0
01405   XSync(handle->dpy, 0);
01406 #endif
01407 
01408   return 0;
01409 }
01410 
01411 
01412 #else
01413 
01414 /* 
01415  *  Win32 Version 
01416  */
01417 
01418 /*
01419  * Spaceball event handling routines
01420  */
01421 
01422 #if defined(USESPACEWARE)
01423 
01424 static spaceballhandle * spaceball_attach(HWND hWnd) {
01425   SiOpenData oData;
01426   enum SpwRetVal res;
01427 
01428   switch (SiInitialize()) {
01429     case SPW_NO_ERROR:         /* init succeeded */
01430       break;
01431 
01432     case SPW_DLL_LOAD_ERROR:   /* driver not installed */
01433     default:                   /* error prevented init */
01434       return NULL;
01435   }
01436 
01437   /* allocate and clear handle data structure */
01438   spaceballhandle *handle = (spaceballhandle *) calloc(1, sizeof(spaceballhandle));
01439 
01440   SiOpenWinInit(&oData, hWnd); /* init win platform data */
01441   SiSetUiMode(handle->sball, SI_UI_ALL_CONTROLS); /* config softbutton display */
01442 
01443   /* start a connection to the device now that the UI mode */
01444   /* and window system data are setup.                              */
01445   handle->sball = SiOpen("OpenGL", SI_ANY_DEVICE, SI_NO_MASK, SI_EVENT, &oData);
01446   if ((handle->sball == NULL) || (handle->sball == SI_NO_HANDLE)) {
01447     SiTerminate(); /* shutdown spaceware input library */
01448     free(handle);
01449     return NULL;
01450   }
01451 
01452   res = SiBeep(handle->sball, "CcCc"); /* beep the spaceball */
01453   if ((handle->sball != NULL) && (handle->sball != SI_NO_HANDLE))
01454     return handle;
01455 
01456   free(handle);
01457   return NULL;
01458 }
01459 
01460 
01461 static void spaceball_close(spaceballhandle *handle) {
01462   if (handle == NULL)
01463     return;
01464 
01465   if (handle->sball != NULL) {
01466     enum SpwRetVal res;
01467     res = SiClose(handle->sball); /* close spaceball device */
01468     if (res != SPW_NO_ERROR)
01469       printf("An error occured during Spaceball shutdown.\n");
01470     SiTerminate(); /* shutdown spaceware input library */
01471   }
01472 
01473   free(handle);
01474 }
01475 
01476 
01477 static int spaceball_decode_event(spaceballhandle *handle, spaceballevent *sballevent, UINT msg, WPARAM wParam, LPARAM lParam) {
01478   if (handle == NULL)
01479     return 0;
01480 
01481   if (handle->sball == NULL)
01482     return 0; /* no spaceball attached/running */
01483 
01484   /* Check to see if this message is a spaceball message */
01485   SiGetEventWinInit(&handle->spwedata, msg, wParam, lParam);
01486 
01487   if (SiGetEvent(handle->sball, 0, &handle->spwedata, &handle->spwevent) == SI_IS_EVENT) {
01488     return 1;
01489   }
01490 
01491   return 0;
01492 }
01493 
01494 #endif /* USESPACEWARE */
01495 
01496 
01497 
01498 static void spaceball_init_event(spaceballevent *sballevent) {
01499   memset(sballevent, 0, sizeof(spaceballevent));
01500 }
01501 
01502 static void spaceball_clear_event(spaceballevent *sballevent) {
01503   sballevent->tx = 0;
01504   sballevent->ty = 0;
01505   sballevent->tz = 0;
01506   sballevent->rx = 0;
01507   sballevent->ry = 0;
01508   sballevent->rz = 0;
01509   sballevent->period = 0;
01510   sballevent->event = 0;
01511 }
01512 
01513 
01514 /*
01515  * declaration of myWindowProc()
01516  */
01517 LRESULT WINAPI myWindowProc( HWND, UINT, WPARAM, LPARAM );
01518 
01519 static const char *szClassName = "OpenGLWindow";
01520 static WNDCLASS  wc;
01521 static int wc_initialized = 0;
01522 
01523 static int OpenWin32Connection(oglhandle * handle) {
01524   HINSTANCE hInstance = GetModuleHandle(NULL);
01525 
01526   if (!wc_initialized) {
01527     /* Clear (important!) and then fill in the window class structure. */
01528     memset(&wc, 0, sizeof(WNDCLASS));
01529     wc.style         = CS_OWNDC;
01530     wc.lpfnWndProc   = (WNDPROC) myWindowProc;
01531     wc.hInstance     = hInstance;
01532     wc.hIcon         = LoadIcon(NULL, IDI_WINLOGO);
01533     wc.hCursor       = LoadCursor(hInstance, IDC_ARROW);
01534     wc.hbrBackground = NULL; /* Default color */
01535     wc.lpszMenuName  = NULL;
01536     wc.lpszClassName = szClassName;
01537 
01538     if(!RegisterClass(&wc)) {
01539       printf("Cannot register window class.\n");
01540       return -1;
01541     }
01542 
01543     wc_initialized = 1;
01544   }
01545 
01546   handle->scrwidth  = GetSystemMetrics(SM_CXSCREEN);
01547   handle->scrheight = GetSystemMetrics(SM_CYSCREEN); 
01548 
01549   return 0;
01550 }
01551 
01552 
01553 static HGLRC SetupOpenGL(oglhandle * handle) {
01554   int nMyPixelFormatID;
01555   HDC hDC;
01556   HGLRC hRC;
01557   PIXELFORMATDESCRIPTOR checkpfd;
01558   static PIXELFORMATDESCRIPTOR pfd = {
01559         sizeof (PIXELFORMATDESCRIPTOR), /* struct size      */
01560         1,                              /* Version number   */
01561         PFD_DRAW_TO_WINDOW      /* Flags, draw to a window, */
01562           | PFD_DOUBLEBUFFER    /* Requires Doublebuffer hw */
01563           | PFD_STEREO          /* we want stereo if possible */
01564           | PFD_SUPPORT_OPENGL, /* use OpenGL               */
01565         PFD_TYPE_RGBA,          /* RGBA pixel values        */
01566         24,                     /* 24-bit color             */
01567         0, 0, 0,                /* RGB bits & shift sizes.  */
01568         0, 0, 0,                /* Don't care about them    */
01569         0, 0,                   /* No alpha buffer info     */
01570         0, 0, 0, 0, 0,          /* No accumulation buffer   */
01571         16,                     /* 16-bit depth buffer      */
01572         1,                      /* Want stencil buffer      */
01573         0,                      /* No auxiliary buffers     */
01574         PFD_MAIN_PLANE,         /* Layer type               */
01575         0,                      /* Reserved (must be 0)     */
01576         0,                      /* No layer mask            */
01577         0,                      /* No visible mask          */
01578         0                       /* No damage mask           */
01579   };
01580 
01581   hDC = GetDC(handle->hWnd);
01582   nMyPixelFormatID = ChoosePixelFormat(hDC, &pfd);
01583 
01584   /* 
01585    * catch errors here.
01586    * If nMyPixelFormat is zero, then there's
01587    * something wrong... most likely the window's
01588    * style bits are incorrect (in CreateWindow() )
01589    * or OpenGL isn't installed on this machine
01590    *
01591    */
01592   if (nMyPixelFormatID == 0) {
01593     printf("Error selecting OpenGL Pixel Format!!\n");
01594     return NULL;
01595   }
01596 
01597   /* check for stereo window */
01598   DescribePixelFormat(hDC, nMyPixelFormatID, 
01599                       sizeof(PIXELFORMATDESCRIPTOR), &checkpfd);
01600   if (checkpfd.dwFlags & PFD_STEREO)
01601     handle->instereo = 1;
01602   else 
01603     handle->instereo = 0;
01604  
01605   SetPixelFormat(hDC, nMyPixelFormatID, &pfd);
01606 
01607   hRC = wglCreateContext(hDC);
01608   ReleaseDC(handle->hWnd, hDC);
01609 
01610   return hRC;
01611 }
01612 
01613 
01614 static int myCreateWindow(oglhandle * handle, const char * wintitle,
01615                           int xpos, int ypos, int xs, int ys) {
01616   /* Create a main window for this application instance. */
01617   handle->hWnd = 
01618         CreateWindow(
01619               szClassName,        /* Window class name */
01620               wintitle,           /* Text for window title bar */
01621               WS_OVERLAPPEDWINDOW /* Window style */
01622                | WS_CLIPCHILDREN
01623                | WS_CLIPSIBLINGS, /* NEED THESE for OpenGL calls to work! */
01624               xpos, ypos,
01625               xs, ys,
01626               NULL,                  /* no parent window                */
01627               NULL,                  /* Use the window class menu.      */
01628               GetModuleHandle(NULL), /* This instance owns this window  */
01629               handle                 /* We don't use any extra data     */
01630         );
01631 
01632   if (!handle->hWnd) {
01633     printf("Couldn't Open Window!!\n");
01634     return -1;
01635   }
01636 
01637   handle->hDC = GetDC(handle->hWnd);
01638   wglMakeCurrent(handle->hDC, handle->hRC);
01639 
01640   /* Make the window visible & update its client area */
01641   ShowWindow( handle->hWnd, SW_SHOW);  /* Show the window         */
01642   UpdateWindow( handle->hWnd );        /* Sends WM_PAINT message  */
01643 
01644   return 0;
01645 }
01646 
01647 
01648 static void win32decodemouse(oglhandle *handle, LPARAM lParam) {
01649   int x, y;
01650   x = LOWORD(lParam);
01651   y = HIWORD(lParam);
01652   /* handle mouse capture in negative range */
01653   if (x & 1 << 15) x -= (1 << 16);
01654   if (y & 1 << 15) y -= (1 << 16);
01655   handle->mousex = x;
01656   handle->mousey = y;
01657 }
01658 
01659 
01660 LRESULT WINAPI myWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
01661   PAINTSTRUCT   ps; /* Paint structure. */
01662   oglhandle *handle;
01663 
01664   /* Upon first window creation, immediately set our user-data field */
01665   /* to store caller-provided handles for this window instance       */
01666   if (msg == WM_NCCREATE) {
01667 #if defined(_M_X64) || defined(_WIN64) || defined(_Wp64)
01668     SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) (((CREATESTRUCT *) lParam)->lpCreateParams));
01669 #elif 1
01670     SetWindowLong(hwnd, GWL_USERDATA, (LONG) (((CREATESTRUCT *) lParam)->lpCreateParams));
01671 #else
01672     SetProp(hwnd, "OGLHANDLE", (((CREATESTRUCT *) lParam)->lpCreateParams));
01673 #endif
01674   }
01675 
01676   /* check to make sure we have a valid window data structure in case */
01677   /* it is destroyed while there are still pending messages...        */
01678 #if defined(_M_X64) || defined(_WIN64) || defined(_Wp64)
01679   handle = (oglhandle *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
01680 #elif 1
01681   handle = (oglhandle *) GetWindowLong(hwnd, GWL_USERDATA);
01682 #else
01683   handle = (oglhandle *) GetProp(hwnd, "OGLHANDLE");
01684 #endif
01685   if (handle == NULL)
01686     return DefWindowProc(hwnd, msg, wParam, lParam);
01687 
01688   switch (msg) {
01689     case WM_CREATE:
01690       handle->hWnd = hwnd; /* must be set before we do anything else */
01691       handle->hRC = SetupOpenGL(handle);
01692       return 0;
01693 
01694     case WM_MOVE:
01695       wglMakeCurrent(handle->hDC, handle->hRC);
01696       handle->xpos = LOWORD(lParam);
01697       handle->ypos = HIWORD(lParam);
01698       return 0;
01699 
01700     case WM_SIZE:
01701       wglMakeCurrent(handle->hDC, handle->hRC);
01702       handle->width  = LOWORD(lParam);
01703       handle->height = HIWORD(lParam);
01704       return 0;
01705 
01706     case WM_KEYDOWN:
01707       handle->evdev = GLWIN_EV_KBD;
01708       /* try to map to ASCII first */
01709       /* handle->evkey = MapVirtualKey((UINT) wParam, MAPVK_VK_TO_CHAR); */
01710       handle->evkey = MapVirtualKey((UINT) wParam, 2);
01711 
01712       if (handle->evkey != 0) {
01713         /* Windows platforms return a raw character (upper case)  */
01714         /* without applying shift-state modifiers, so we manually */
01715         /* query shift key modifier state and apply the modifier  */
01716         /* ourselves w/ toupper()/tolower().                      */
01717         int shiftstate = ((handle->MouseFlags & MK_SHIFT) != 0);
01718         handle->evkey = (shiftstate) ? toupper(handle->evkey) : tolower(handle->evkey);
01719       } else {
01720         /* if no ASCII code, try mapping to a virtual key scan code,  */
01721         /* but don't bother distinguishing which left/right key it is */
01722         /*unsigned int keysym = MapVirtualKey((UINT) wParam, MAPVK_VK_TO_VSC);*/
01723         unsigned int keysym = (unsigned int) wParam;
01724 
01725         switch (keysym) {
01726           case VK_UP:          handle->evdev = GLWIN_EV_KBD_UP;        break;
01727           case VK_DOWN:        handle->evdev = GLWIN_EV_KBD_DOWN;      break;
01728           case VK_LEFT:        handle->evdev = GLWIN_EV_KBD_LEFT;      break;
01729           case VK_RIGHT:       handle->evdev = GLWIN_EV_KBD_RIGHT;     break;
01730           case VK_PRIOR:       handle->evdev = GLWIN_EV_KBD_PAGE_UP;   break;
01731           case VK_NEXT:        handle->evdev = GLWIN_EV_KBD_PAGE_UP;   break;
01732           case VK_HOME:        handle->evdev = GLWIN_EV_KBD_HOME;      break;
01733           case VK_END:         handle->evdev = GLWIN_EV_KBD_END;       break;
01734           case VK_INSERT:      handle->evdev = GLWIN_EV_KBD_INSERT;    break;
01735           case VK_DELETE:      handle->evdev = GLWIN_EV_KBD_DELETE;    break;
01736 
01737           case VK_F1:          handle->evdev = GLWIN_EV_KBD_F1;        break;
01738           case VK_F2:          handle->evdev = GLWIN_EV_KBD_F2;        break;
01739           case VK_F3:          handle->evdev = GLWIN_EV_KBD_F3;        break;
01740           case VK_F4:          handle->evdev = GLWIN_EV_KBD_F4;        break;
01741           case VK_F5:          handle->evdev = GLWIN_EV_KBD_F5;        break;
01742           case VK_F6:          handle->evdev = GLWIN_EV_KBD_F6;        break;
01743           case VK_F7:          handle->evdev = GLWIN_EV_KBD_F7;        break;
01744           case VK_F8:          handle->evdev = GLWIN_EV_KBD_F8;        break;
01745           case VK_F9:          handle->evdev = GLWIN_EV_KBD_F9;        break;
01746           case VK_F10:         handle->evdev = GLWIN_EV_KBD_F10;       break;
01747           case VK_F11:         handle->evdev = GLWIN_EV_KBD_F11;       break;
01748           case VK_F12:         handle->evdev = GLWIN_EV_KBD_F12;       break;
01749 
01750           case VK_ESCAPE:      handle->evdev = GLWIN_EV_KBD_ESC;       break;
01751 
01752           default:
01753             handle->evdev = GLWIN_EV_NONE;
01754             break;
01755         }
01756       }
01757       return 0;
01758 
01759     case WM_MOUSEMOVE:
01760       win32decodemouse(handle, lParam);
01761       handle->evdev = GLWIN_EV_MOUSE_MOVE;
01762       handle->MouseFlags = (long) wParam;
01763       if (!(handle->MouseFlags & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)))
01764         ReleaseCapture();
01765       return 0;
01766 
01767     case WM_MOUSEWHEEL:
01768       {
01769         int wheeldelta = ((short) HIWORD(wParam));
01770         if (wheeldelta > (WHEEL_DELTA / 2)) {
01771           handle->evdev = GLWIN_EV_MOUSE_WHEELUP;
01772         } else if (wheeldelta < -(WHEEL_DELTA / 2)) {
01773           handle->evdev = GLWIN_EV_MOUSE_WHEELDOWN;
01774         }
01775       }
01776       return 0;
01777 
01778     case WM_LBUTTONDOWN:
01779       SetCapture(hwnd);
01780       win32decodemouse(handle, lParam);
01781       handle->MouseFlags = (long) wParam;
01782       handle->evdev = GLWIN_EV_MOUSE_LEFT;
01783       handle->evval = 1;
01784       return 0;
01785 
01786     case WM_LBUTTONUP:
01787       win32decodemouse(handle, lParam);
01788       handle->MouseFlags = (long) wParam;
01789       handle->evdev = GLWIN_EV_MOUSE_LEFT;
01790       handle->evval = 0;
01791       if (!(handle->MouseFlags & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)))
01792         ReleaseCapture();
01793       return 0;
01794 
01795     case WM_MBUTTONDOWN:
01796       SetCapture(hwnd);
01797       win32decodemouse(handle, lParam);
01798       handle->MouseFlags = (long) wParam;
01799       handle->evdev = GLWIN_EV_MOUSE_MIDDLE;
01800       handle->evval = 1;
01801       return 0;
01802 
01803     case WM_MBUTTONUP:
01804       win32decodemouse(handle, lParam);
01805       handle->MouseFlags = (long) wParam;
01806       handle->evdev = GLWIN_EV_MOUSE_MIDDLE;
01807       handle->evval = 0;
01808       if (!(handle->MouseFlags & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)))
01809         ReleaseCapture();
01810       return 0;
01811 
01812     case WM_RBUTTONDOWN:
01813       SetCapture(hwnd);
01814       win32decodemouse(handle, lParam);
01815       handle->MouseFlags = (long) wParam;
01816       handle->evdev = GLWIN_EV_MOUSE_RIGHT;
01817       handle->evval = 1;
01818       return 0;
01819 
01820     case WM_RBUTTONUP:
01821       win32decodemouse(handle, lParam);
01822       handle->MouseFlags = (long) wParam;
01823       handle->evdev = GLWIN_EV_MOUSE_RIGHT;
01824       handle->evval = 0;
01825       if (!(handle->MouseFlags & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)))
01826         ReleaseCapture();
01827       return 0;
01828 
01829     case WM_CLOSE:
01830 #if 1
01831       DestroyWindow(handle->hWnd);
01832 #else
01833       PostQuitMessage(0);
01834 #endif
01835       return 0;
01836 
01837     case WM_PAINT:
01838       BeginPaint(hwnd, &ps);
01839       EndPaint(hwnd, &ps);
01840       return 0;
01841 
01842     case WM_SIZING:
01843       glClear(GL_COLOR_BUFFER_BIT);
01844       SwapBuffers(handle->hDC);
01845       glDrawBuffer(GL_BACK);
01846       return 0;
01847 
01848     case WM_SETCURSOR:
01849       if (LOWORD(lParam) == HTCLIENT) {
01850         SetCursor(LoadCursor(NULL, IDC_ARROW));
01851         return 0;
01852       }
01853       return DefWindowProc(hwnd, msg, wParam, lParam);
01854 
01855     default:
01856       return DefWindowProc(hwnd, msg, wParam, lParam);
01857   }
01858 
01859   return 0;
01860 }
01861 
01862 
01863 void * glwin_create(const char * wintitle, int width, int height) {
01864   oglhandle * handle;
01865   int rc;
01866   GLint stencilbits;
01867 
01868   handle = (oglhandle *) calloc(1, sizeof(oglhandle));
01869   if (handle == NULL)
01870     return NULL;
01871 
01872   handle->havestencil=0; /* initialize stencil state */
01873   handle->instereo=0;    /* mark this as a non-stereo window */
01874 
01875   handle->width = width;
01876   handle->height = height;
01877   handle->evdev = GLWIN_EV_NONE;
01878 
01879   rc = OpenWin32Connection(handle);
01880   if (rc != 0) {
01881     printf("OpenWin32Connection() returned an error!\n");
01882     free(handle);
01883     return NULL;
01884   } 
01885 
01886   handle->width = width;
01887   handle->height = height;
01888   
01889   rc = myCreateWindow(handle, wintitle, 0, 0, width, height); 
01890   if (rc != 0) {
01891     printf("CreateWindow() returned an error!\n");
01892     free(handle);
01893     return NULL;
01894   } 
01895 
01896   /* Enable Spaceball events to this window */
01897 #if 0
01898   handle->sball = spaceball_attach(handle->win);
01899 #endif
01900   /* initialize spaceball event structure   */
01901   spaceball_init_event(&handle->sballevent);
01902   spaceball_clear_event(&handle->sballevent);
01903 
01904   /* check for an OpenGL stencil buffer */
01905   glGetIntegerv(GL_STENCIL_BITS, &stencilbits);
01906   if (stencilbits > 0) {
01907     handle->havestencil = 1;
01908   }
01909 
01910   return handle;
01911 }
01912 
01913 
01914 void glwin_destroy(void * voidhandle) {
01915   oglhandle * handle = (oglhandle *) voidhandle;
01916 
01917   wglDeleteContext(handle->hRC);
01918 #if 1
01919   DestroyWindow(handle->hWnd);
01920 #else
01921   PostQuitMessage( 0 );
01922 #endif
01923 
01924   /* glwin_handle_events(handle, GLWIN_EV_POLL_NONBLOCK); */
01925 }
01926 
01927 
01928 void glwin_swap_buffers(void * voidhandle) {
01929   oglhandle * handle = (oglhandle *) voidhandle;
01930   glFlush();
01931   SwapBuffers(handle->hDC);
01932   glDrawBuffer(GL_BACK);
01933 }
01934 
01935 
01936 int glwin_handle_events(void * voidhandle, int evblockmode) {
01937   oglhandle * handle = (oglhandle *) voidhandle;
01938   MSG msg;
01939   int rc=0;
01940   int pending=0;
01941 
01942   handle->evdev = GLWIN_EV_NONE;
01943   handle->evval = 0;
01944   handle->evkey = '\0';
01945 
01946   /* This pumps the Windows message queue, forcing events to be updated */
01947   /* by the time we return from DispatchMessage.                        */
01948   pending=PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
01949   while (!rc && (evblockmode || pending)) {
01950     if (pending) {
01951       TranslateMessage(&msg); /* translate the message          */
01952       DispatchMessage(&msg);  /* fire it off to the window proc */
01953       pending=0;
01954     } else if (evblockmode == GLWIN_EV_POLL_BLOCK) {
01955       if (GetMessage(&msg, NULL, 0, 0)) {
01956         TranslateMessage(&msg);
01957         DispatchMessage(&msg);
01958       }
01959     } else {
01960       if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
01961         TranslateMessage(&msg); /* translate the message          */
01962         DispatchMessage(&msg);  /* fire it off to the window proc */
01963       }
01964     }
01965     if (handle->evdev != GLWIN_EV_NONE)
01966       rc=1;
01967   }
01968 
01969   return rc;
01970 }
01971 
01972 
01973 int glwin_resize(void *voidhandle, int width, int height) {
01974   RECT rcClient, rcWindow;
01975   POINT ptDiff;
01976   oglhandle * handle = (oglhandle *) voidhandle;
01977   if (handle == NULL)
01978     return -1;
01979 
01980   GetClientRect(handle->hWnd, &rcClient);
01981   GetWindowRect(handle->hWnd, &rcWindow);
01982   ptDiff.x = (rcWindow.right - rcWindow.left) - rcClient.right;
01983   ptDiff.y = (rcWindow.bottom - rcWindow.top) - rcClient.bottom;
01984   MoveWindow(handle->hWnd, rcWindow.left, rcWindow.top, width + ptDiff.x, height + ptDiff.y, TRUE);
01985 
01986   return 0;
01987 }
01988 
01989 
01990 int glwin_reposition(void *voidhandle, int xpos, int ypos) {
01991   RECT rcClient, rcWindow;
01992   oglhandle * handle = (oglhandle *) voidhandle;
01993   if (handle == NULL)
01994     return -1;
01995 
01996   GetClientRect(handle->hWnd, &rcClient);
01997   GetWindowRect(handle->hWnd, &rcWindow);
01998   MoveWindow(handle->hWnd, xpos, ypos, rcWindow.right-rcWindow.left, rcWindow.bottom-rcWindow.top, TRUE);
01999 
02000   return 0;
02001 }
02002 
02003 
02004 int glwin_fullscreen(void * voidhandle, int fson, int xinescreen) {
02005   return -1;
02006 }  
02007 
02008 #endif
02009 
02010 
02011 /* 
02012  * Code used for both Windows and Linux 
02013  */
02014 int glwin_query_extension(const char *extname) {
02015   char *ext;
02016   char *endext;
02017   if (!extname)
02018     return 0;
02019 
02020   /* search for extension in list of available extensions */
02021   ext = (char *) glGetString(GL_EXTENSIONS);
02022   if (ext != NULL) {
02023     endext = ext + strlen(ext);
02024     while (ext < endext) {
02025       size_t n = strcspn(ext, " ");
02026       if ((strlen(extname) == n) && (strncmp(extname, ext, n) == 0)) {
02027         return 1; /* extension is available */
02028         break;
02029       }
02030       ext += (n + 1);
02031     }
02032   }
02033 
02034   return 0; /* False, extension is not available */
02035 }
02036 
02037 
02038 int glwin_query_vsync(void *voidhandle, int *onoff) {
02039   oglhandle * handle = (oglhandle *) voidhandle;
02040   if (handle == NULL)
02041     return GLWIN_ERROR; 
02042 
02043 #if defined(GLX_EXT_swap_control)
02044   if (glx_query_extension(handle->dpy, "GLX_EXT_swap_control")) {
02045     int interval = 0;
02046     unsigned int tmp = -1;
02047     glXQueryDrawable(handle->dpy, glXGetCurrentDrawable(), GLX_SWAP_INTERVAL_EXT, &tmp);
02048     interval = tmp;
02049     if (interval > 0) {
02050       *onoff = 1;
02051     } else { 
02052       *onoff = 0;
02053     }
02054     return GLWIN_SUCCESS;
02055   }
02056 #elif 0
02057   GLuint count = 0;
02058   glwin_ext_fctns *ext = handle->ext;
02059   if (ext->hasgetvideosyncsgi) {
02060     /* XXX this doesn't help much since we get non-zero counts */
02061     /* even when using a screen with vsync disabled            */
02062     if (GLXGETVIDEOSYNCSGI(&count) == 0) {
02063       if (count > 0) {
02064         *onoff = 1;
02065       } else { 
02066         *onoff = 0;
02067       }
02068     }
02069     return GLWIN_SUCCESS;
02070   }
02071 #endif
02072 
02073   return GLWIN_NOT_IMPLEMENTED;
02074 }
02075 
02076 
02077 #if !(defined(WIN32) || defined(_WIN64))
02078 
02079 typedef struct {
02080   int isvalid;
02081   GLenum drawbufs[16];
02082   GLuint fbo;
02083   GLuint tex;
02084   GLuint depth;
02085 } glwin_fbo_target;
02086 
02087 
02088 int glwin_fbo_target_bind(void *voidhandle, void *voidtarget) {
02089   oglhandle * handle = (oglhandle *) voidhandle;
02090   glwin_fbo_target * fb = (glwin_fbo_target *) voidtarget;
02091   if (handle == NULL || fb == NULL)
02092     return GLWIN_ERROR; 
02093   glwin_ext_fctns *ext = handle->ext;
02094 
02095   GLBINDFRAMEBUFFER(GL_FRAMEBUFFER, fb->fbo); /* bind FBO */
02096 
02097   return GLWIN_SUCCESS; 
02098 }
02099 
02100 
02101 int glwin_fbo_target_unbind(void *voidhandle, void *voidtarget) {
02102   oglhandle * handle = (oglhandle *) voidhandle;
02103   glwin_fbo_target * fb = (glwin_fbo_target *) voidtarget;
02104   if (handle == NULL || fb == NULL)
02105     return GLWIN_ERROR; 
02106   glwin_ext_fctns *ext = handle->ext;
02107 
02108   GLBINDFRAMEBUFFER(GL_FRAMEBUFFER, 0); /* bind the normal framebuffer */
02109 
02110   return GLWIN_SUCCESS; 
02111 }
02112 
02113 
02114 int glwin_fbo_target_destroy(void *voidhandle, void *voidtarget) {
02115   oglhandle * handle = (oglhandle *) voidhandle;
02116   glwin_fbo_target * fb = (glwin_fbo_target *) voidtarget;
02117   if (handle == NULL || fb == NULL)
02118     return GLWIN_ERROR; 
02119   glwin_ext_fctns *ext = handle->ext;
02120 
02121   GLDELETERENDERBUFFERS(1, &fb->depth);
02122   GLDELETEFRAMEBUFFERS(1, &fb->fbo);
02123   glDeleteTextures(1, &fb->tex);
02124   free(fb);
02125 
02126   return GLWIN_SUCCESS; 
02127 }
02128 
02129 
02130 int glwin_fbo_target_resize(void *voidhandle, void *voidtarget, int wsx, int wsy) {
02131   oglhandle * handle = (oglhandle *) voidhandle;
02132   glwin_fbo_target * fb = (glwin_fbo_target *) voidtarget;
02133   if (handle == NULL || fb == NULL)
02134     return GLWIN_ERROR;
02135   glwin_ext_fctns *ext = handle->ext;
02136 
02137 #if 0
02138   printf("\nglwin_fbo_target_resize(): W %d x %d\n", wsx, wsy); 
02139 #endif
02140 
02141   GLBINDFRAMEBUFFER(GL_FRAMEBUFFER, fb->fbo);
02142 
02143   glBindTexture(GL_TEXTURE_2D, fb->tex);
02144   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, wsx, wsy, 0,
02145                GL_RGBA, GL_UNSIGNED_BYTE, 0);
02146   GLFRAMEBUFFERTEXTURE2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 
02147                          GL_TEXTURE_2D, fb->tex, 0);
02148   GLBINDRENDERBUFFER(GL_RENDERBUFFER, fb->depth);
02149   GLRENDERBUFFERSTORAGE(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, wsx, wsy);
02150   GLFRAMEBUFFERRENDERBUFFER(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 
02151                             GL_RENDERBUFFER, fb->depth);
02152   if (GLCHECKFRAMEBUFFERSTATUS(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
02153     return GLWIN_ERROR;
02154   }
02155 
02156   fb->drawbufs[0] = GL_COLOR_ATTACHMENT0;
02157   GLDRAWBUFFERS(1, fb->drawbufs);
02158 
02159   return GLWIN_SUCCESS;
02160 }
02161 
02162 
02163 void *glwin_fbo_target_create(void *voidhandle, int wsx, int wsy) {
02164   oglhandle * handle = (oglhandle *) voidhandle;
02165   if (handle == NULL)
02166     return NULL;
02167   glwin_ext_fctns *ext = handle->ext;
02168 
02169   if (!ext->hasglfborendertarget)
02170     return NULL;  /* fail out if the required GL extensions aren't available */
02171 
02172   glwin_fbo_target *fb = 
02173     (glwin_fbo_target *) calloc(1, sizeof(glwin_fbo_target));
02174 
02175   if (fb != NULL) {
02176     /* create target texture */
02177     glGenTextures(1, &fb->tex);
02178     glBindTexture(GL_TEXTURE_2D, fb->tex);
02179 
02180     /* set tex mode to replace... */
02181     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
02182 
02183     /* we need to use nearest-pixel filtering... */
02184 #if 1
02185     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
02186     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
02187 #else
02188     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
02189     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
02190 #endif
02191     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
02192     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
02193 #if 1
02194     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, wsx, wsy, 0,
02195                  GL_RGBA, GL_UNSIGNED_BYTE, 0);
02196 #else
02197     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, wsx, wsy, 0,
02198                  GL_RGBA, GL_UNSIGNED_BYTE, 0);
02199 #endif
02200     glBindTexture(GL_TEXTURE_2D, 0); /* XXX may not need this */
02201 
02202 
02203     /* create RBO for depth buffer */
02204     GLGENRENDERBUFFERS(1, &fb->depth);
02205     GLBINDRENDERBUFFER(GL_RENDERBUFFER, fb->depth);
02206     GLRENDERBUFFERSTORAGE(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, wsx, wsy);
02207     GLBINDRENDERBUFFER(GL_RENDERBUFFER, 0); /* XXX not sure if necessary */
02208 
02209 
02210     /* create FBO */
02211     GLGENFRAMEBUFFERS(1, &fb->fbo);
02212     GLBINDFRAMEBUFFER(GL_FRAMEBUFFER, fb->fbo);
02213 
02214     /* Set "renderedTexture" as our colour attachement #0 */
02215     GLFRAMEBUFFERTEXTURE2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 
02216                            GL_TEXTURE_2D, fb->tex, 0);
02217 
02218     /* attach FBO to depth buffer attachment point */
02219     GLFRAMEBUFFERRENDERBUFFER(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
02220                               GL_RENDERBUFFER, fb->depth);
02221 
02222     if (GLCHECKFRAMEBUFFERSTATUS(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
02223       return NULL;
02224     }
02225 
02226     /* set the list of draw buffers. */
02227     fb->drawbufs[0] = GL_COLOR_ATTACHMENT0;
02228     GLDRAWBUFFERS(1, fb->drawbufs); /* 1 is number of bufs */
02229  
02230     /* switch back to window system framebuffer */
02231     GLBINDFRAMEBUFFER(GL_FRAMEBUFFER, 0);
02232   }
02233 
02234 #if 0
02235   if (glwin_fbo_target_resize(voidhandle, fb, wsx, wsy) == GLWIN_ERROR) {
02236     glwin_fbo_target_destroy(voidhandle, fb);
02237     return NULL;
02238   }
02239 #endif
02240 
02241   return fb;
02242 }
02243 
02244 
02245 int glwin_fbo_target_draw_normal(void *voidhandle, void *voidtarget) {
02246   oglhandle * handle = (oglhandle *) voidhandle;
02247   glwin_fbo_target * fb = (glwin_fbo_target *) voidtarget;
02248   if (handle == NULL || fb == NULL)
02249     return GLWIN_ERROR;
02250   glwin_ext_fctns *ext = handle->ext;
02251 
02252   GLBINDFRAMEBUFFER(GL_FRAMEBUFFER, 0); /* bind standard framebuffer */
02253 
02254   return GLWIN_SUCCESS;
02255 }
02256 
02257 
02258 int glwin_fbo_target_draw_fbo(void *voidhandle, void *voidtarget, int wsx, int wsy) {
02259   oglhandle * handle = (oglhandle *) voidhandle;
02260   glwin_fbo_target * fb = (glwin_fbo_target *) voidtarget;
02261   if (handle == NULL || fb == NULL)
02262     return GLWIN_ERROR;
02263 
02264   /* render to the screen */
02265   glwin_fbo_target_unbind(voidhandle, voidtarget);
02266 
02267   glBindTexture(GL_TEXTURE_2D, fb->tex);
02268   glEnable(GL_TEXTURE_2D);
02269   glColor3f(0.0, 0.0, 1.0);
02270   glBegin(GL_QUADS);
02271     glTexCoord2f(0.0f, 0.0f);
02272     glVertex2f(0, 0);
02273     glTexCoord2f(0.0f, 1.0f);
02274     glVertex2f(0, wsy);
02275     glTexCoord2f(1.0f, 1.0f);
02276     glVertex2f(wsx, wsy);
02277     glTexCoord2f(1.0f, 0.0f);
02278     glVertex2f(wsx, 0);
02279   glEnd();
02280   glDisable(GL_TEXTURE_2D);
02281 
02282   return GLWIN_SUCCESS;
02283 }
02284 
02285 
02286 /*
02287  * HMD-specific FBO renderer
02288  */
02289 
02290 #define HMD_DIVCNT 10
02291 
02292 static void hmd_compute_warped_coords(int divcnt, int wsx, int wsy, 
02293                                       float rscale, float wscale,
02294                                       float *xcrds, float *ycrds,
02295                                       const float *user_distort_coeff5) {
02296   float divs = (float) divcnt;
02297   float hwidth = wsx / 2.0f;
02298   float hwdiv = hwidth / divs;
02299   float hdiv = wsy / divs;
02300   float cx=hwidth / 2.0f;
02301   float cy=wsy / 2.0f;
02302   float x, y;
02303 
02304   /* assume Oculus DK2 coefficients if caller doesn't specify */
02305   const float dk2_warp_coeff[5] = { 1.000f, 0.000f, 0.220f, 0.000f, 0.240f };
02306 #if 0
02307   const float msr_warp_coeff[5] = { 1.000f, 0.290f, 0.195f, 0.045f, 0.360f };
02308 #endif
02309   const float *C = dk2_warp_coeff;
02310 
02311   /*
02312    * use caller-provided distortion correction coefficients when 
02313    * available, otherwise assume Oculus DK2 
02314    */
02315   if (user_distort_coeff5)
02316     C = user_distort_coeff5;
02317 
02318   int ix, iy;
02319   for (iy=0; iy<=divcnt; iy++) {
02320     for (ix=0; ix<=divcnt; ix++) {
02321       float drx, dry, r, r2, rnew;
02322       int addr = iy*(divcnt+1) + ix;
02323       x = ix * hwdiv;
02324       y = iy * hdiv;
02325 
02326       /* HMD image barrel distortion warping */
02327       float rnorm = wsy * 1.0f;
02328       drx = (x - cx) / rnorm;
02329       dry = (y - cy) / rnorm;
02330       r2 = drx*drx + dry*dry;
02331       r = sqrt(r2); 
02332 
02333       rnew = C[0] + r*C[1] + r2*C[2] + r*r2*C[3] + r2*r2*C[4];
02334 
02335       rnew = 1.0f/rnew;
02336       rnorm *= 1.0f * rscale;
02337       x = wscale * rnorm * rnew * drx + cx; 
02338       y =          rnorm * rnew * dry + cy; 
02339 
02340       xcrds[addr] = x;
02341       ycrds[addr] = y;
02342     }
02343   }
02344 }
02345 
02346 
02347 /* draw lines w/ HMD warp correction to check remaining optical distortions */
02348 static void hmd_draw_eye_lines(int divcnt, int xoff, int width, int height, 
02349                                float *xcrds, float *ycrds) {
02350   float x, y;
02351   int ix, iy;
02352 
02353   glDisable(GL_TEXTURE_2D);
02354   glColor3f(1.0f, 1.0f, 1.0f);
02355 
02356   for (iy=0; iy<=divcnt; iy++) {
02357     for (ix=0; ix<divcnt; ix++) {
02358       int addr = iy*(divcnt+1) + ix;
02359       y = ycrds[addr];
02360       x = xcrds[addr] + xoff;
02361       float xn = xcrds[addr+1] + xoff;
02362       float yn = ycrds[addr+1];
02363       glBegin(GL_LINES);
02364       glVertex2f(x, y);
02365       glVertex2f(xn, yn);
02366       glEnd();
02367     }
02368   }
02369   for (ix=0; ix<=divcnt; ix++) {
02370     for (iy=0; iy<divcnt; iy++) {
02371       int addr = iy*(divcnt+1) + ix;
02372       x = xcrds[addr] + xoff;
02373       y = ycrds[addr];
02374       float xn = xcrds[addr + divcnt+1] + xoff;
02375       float yn = ycrds[addr + divcnt+1];
02376       glBegin(GL_LINES);
02377       glVertex2f(x, y);
02378       glVertex2f(xn, yn);
02379       glEnd();
02380     }
02381   }
02382 }
02383 
02384 
02385 /* draw quads w/ HMD warp correction */
02386 static void hmd_draw_eye_texquads(int divcnt, int xoff, int width, int height, 
02387                                   float *xcrds, float *ycrds) {
02388   float divs = (float) divcnt;
02389   float xtxdiv = 0.5f / divs;
02390   float ytxdiv = 1.0f / divs;
02391   float tx, ty;
02392   int ix, iy;
02393   float txoff = xoff / ((float) width);
02394 
02395   glBegin(GL_QUADS);
02396   for (iy=0,ty=1.0f; iy<divcnt; iy++,ty-=ytxdiv) {
02397     float tyn = ty-ytxdiv;
02398     for (ix=0,tx=0.0f; ix<divcnt; ix++,tx+=xtxdiv) {
02399       float txn = tx+xtxdiv;
02400       int addr = iy*(divcnt+1) + ix;
02401       float xx0y0 = xcrds[addr] + xoff;
02402       float yx0y0 = ycrds[addr];
02403       float xx1y0 = xcrds[addr + 1] + xoff;
02404       float yx1y0 = ycrds[addr + 1];
02405       float xx0y1 = xcrds[addr     + divcnt+1] + xoff;
02406       float yx0y1 = ycrds[addr     + divcnt+1];
02407       float xx1y1 = xcrds[addr + 1 + divcnt+1] + xoff;
02408       float yx1y1 = ycrds[addr + 1 + divcnt+1];
02409 
02410       glTexCoord2f(tx+txoff, ty);
02411       glVertex2f(xx0y0, yx0y0);
02412       glTexCoord2f(tx+txoff, tyn);
02413       glVertex2f(xx0y1, yx0y1);
02414       glTexCoord2f(txn+txoff, tyn);
02415       glVertex2f(xx1y1, yx1y1);
02416       glTexCoord2f(txn+txoff, ty);
02417       glVertex2f(xx1y0, yx1y0);
02418     }
02419   }
02420   glEnd();
02421 }
02422 
02423 
02424 /*
02425  * Structures for HMD spheremap display and image warping for
02426  * eye lens distortion correction
02427  */
02428 
02429 typedef struct {
02430   void *hmd_fbo;
02431   int divcnt;
02432   int wsx;       /* window dimensions */
02433   int wsy;   
02434   int wrot;      /* flag indicating that window is rotated vs. HMD image */
02435   int ixs;       /* image size */
02436   int iys;       
02437   float *xcrds;  /* use if there chromatic aberration is unnecessary */
02438   float *ycrds;
02439 
02440   /* chromatic aberration correction */
02441   float *Rxcrds;
02442   float *Rycrds;
02443   float *Gxcrds;
02444   float *Gycrds;
02445   float *Bxcrds;
02446   float *Bycrds;
02447 } glwin_warp_hmd;
02448 
02449 
02450 void glwin_spheremap_update_hmd_warp(void *vwin, void *voidwarp, 
02451                                      int wsx, int wsy, 
02452                                      int warpdivs, int ixs, int iys,
02453                                      const float *barrel_coeff, int force) {
02454   glwin_warp_hmd * warp = (glwin_warp_hmd *) voidwarp;
02455  
02456   if (force || warp->divcnt!=warpdivs || warp->wsx!=wsx || warp->wsy!=wsy) {
02457     const float Oculus_DK2_coeff[4] = { 1.0f, 0.22f, 0.24f, 0.0f };
02458     /* const float Oculus_DK1_coeff[4] = { 1.0f, 0.18f, 0.115f, 0.0f }; */
02459     if (!barrel_coeff) 
02460       barrel_coeff = Oculus_DK2_coeff;
02461 
02462 #if 0
02463     printf("glwin_spheremap_update_hmd_warp(): W %d x %d, I %d x %d\n", 
02464            wsx, wsy, ixs, iys); 
02465     printf("warp: %.3f, %.3f, %.3f, %.3f\n",
02466            barrel_coeff[0], barrel_coeff[1], barrel_coeff[2], barrel_coeff[3]);
02467 #endif
02468 
02469 
02470     /* update FBO target for new window size */
02471     if (glwin_fbo_target_resize(vwin, warp->hmd_fbo, wsx, wsy) == GLWIN_ERROR) {
02472       printf("\nglwin_spheremap_update_hmd_warp(): "
02473              "an error occured resizing the FBO!\n");
02474     }
02475 
02476     /*
02477      * recompute the warp mesh 
02478      */
02479     if (warp->xcrds != NULL)
02480       free(warp->xcrds);
02481     if (warp->ycrds != NULL)
02482       free(warp->ycrds);
02483 
02484     if (warp->Rxcrds != NULL)
02485       free(warp->Rxcrds);
02486     if (warp->Rycrds != NULL)
02487       free(warp->Rycrds);
02488     if (warp->Gxcrds != NULL)
02489       free(warp->Gxcrds);
02490     if (warp->Gycrds != NULL)
02491       free(warp->Gycrds);
02492     if (warp->Bxcrds != NULL)
02493       free(warp->Bxcrds);
02494     if (warp->Bycrds != NULL)
02495       free(warp->Bycrds);
02496 
02497     warp->wsx = wsx;
02498     warp->wsy = wsy;
02499     warp->divcnt = warpdivs;
02500     warp->xcrds  = (float *) calloc(1, warpdivs*warpdivs*sizeof(float)); 
02501     warp->ycrds  = (float *) calloc(1, warpdivs*warpdivs*sizeof(float)); 
02502     warp->Rxcrds = (float *) calloc(1, warpdivs*warpdivs*sizeof(float)); 
02503     warp->Rycrds = (float *) calloc(1, warpdivs*warpdivs*sizeof(float)); 
02504     warp->Gxcrds = (float *) calloc(1, warpdivs*warpdivs*sizeof(float)); 
02505     warp->Gycrds = (float *) calloc(1, warpdivs*warpdivs*sizeof(float)); 
02506     warp->Bxcrds = (float *) calloc(1, warpdivs*warpdivs*sizeof(float)); 
02507     warp->Bycrds = (float *) calloc(1, warpdivs*warpdivs*sizeof(float)); 
02508 
02509     /* plain image w/ no chromatic aberration correction */
02510     hmd_compute_warped_coords(warpdivs-1, wsx, wsy, 1.0f, 1.0f, 
02511                               warp->xcrds, warp->ycrds, barrel_coeff);
02512 
02513     /* set of RGB meshes for chromatic aberration correction */
02514     const float Rscale  = 1.015f;
02515     const float Gscale  = 1.000f;
02516     const float Bscale  = 0.980f;
02517 
02518     hmd_compute_warped_coords(warpdivs-1, wsx,wsy, Rscale, 1.0f, 
02519                               warp->Rxcrds, warp->Rycrds, barrel_coeff);
02520     hmd_compute_warped_coords(warpdivs-1, wsx,wsy, Gscale, 1.0f, 
02521                               warp->Gxcrds, warp->Gycrds, barrel_coeff);
02522     hmd_compute_warped_coords(warpdivs-1, wsx,wsy, Bscale, 1.0f, 
02523                               warp->Bxcrds, warp->Bycrds, barrel_coeff);
02524   }
02525 }
02526 
02527 
02528 void glwin_spheremap_destroy_hmd_warp(void *vwin, void *voidwarp) {
02529   glwin_warp_hmd * warp = (glwin_warp_hmd *) voidwarp;
02530   glwin_fbo_target_destroy(vwin, warp->hmd_fbo);
02531 
02532   if (warp->xcrds != NULL)
02533     free(warp->xcrds);
02534   if (warp->ycrds != NULL)
02535     free(warp->ycrds);
02536 
02537   if (warp->Rxcrds != NULL)
02538     free(warp->Rxcrds);
02539   if (warp->Rycrds != NULL)
02540     free(warp->Rycrds);
02541   if (warp->Gxcrds != NULL)
02542     free(warp->Gxcrds);
02543   if (warp->Gycrds != NULL)
02544     free(warp->Gycrds);
02545   if (warp->Bxcrds != NULL)
02546     free(warp->Bxcrds);
02547   if (warp->Bycrds != NULL)
02548     free(warp->Bycrds);
02549   free(warp);
02550 }
02551 
02552 
02553 void * glwin_spheremap_create_hmd_warp(void *vwin, int wsx, int wsy, int wrot,
02554                                        int warpdivs, int ixs, int iys,
02555                                        const float *user_coeff) {
02556   glwin_warp_hmd *warp = (glwin_warp_hmd *) calloc(1, sizeof(glwin_warp_hmd));
02557   warp->hmd_fbo = glwin_fbo_target_create(vwin, wsx, wsy);
02558   warp->wrot = wrot;
02559   glwin_spheremap_update_hmd_warp(vwin, warp, wsx, wsy, warpdivs, 
02560                                   ixs, iys, user_coeff, 1);
02561   return warp;
02562 }
02563 
02564 
02565 int glwin_spheremap_draw_hmd_warp(void *vwin, void *voidwarp, 
02566                                   int drawimage, int drawlines, int chromcorr,
02567                                   int wsx, int wsy, int ixs, int iys, 
02568                                   const float *hmdquat,
02569                                   float fov, float rad, int hmd_spres) {
02570   oglhandle * handle = (oglhandle *) vwin;
02571   glwin_warp_hmd * warp = (glwin_warp_hmd *) voidwarp;
02572   glwin_fbo_target * fb = (glwin_fbo_target *) warp->hmd_fbo;
02573   if (handle == NULL || warp == NULL)
02574     return GLWIN_ERROR;
02575 
02576   glBindTexture(GL_TEXTURE_2D, 0); /* bind the RT image before drawing */
02577   glEnable(GL_TEXTURE_2D);
02578 
02579   glwin_fbo_target_bind(vwin, warp->hmd_fbo);
02580   glwin_spheremap_draw_tex(vwin, GLWIN_STEREO_OVERUNDER, 
02581                            ixs, iys, hmdquat, fov, rad, hmd_spres);
02582   glwin_fbo_target_unbind(vwin, warp->hmd_fbo); /* render to the screen */
02583 
02584   glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
02585   glClearColor(0.0, 0.0, 0.0, 1.0); /* black */
02586   glViewport(0, 0, wsx, wsy);
02587   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
02588 
02589   glShadeModel(GL_SMOOTH);
02590   glMatrixMode(GL_PROJECTION);
02591   glLoadIdentity();
02592   glOrtho(0.0, wsx, wsy, 0.0, -1.0, 1.0);
02593   glMatrixMode(GL_MODELVIEW);
02594   glLoadIdentity();
02595 
02596   float hw = wsx * 0.5f;
02597   int dm1 = warp->divcnt-1;
02598 
02599 
02600   /*
02601    * draw texture map FBO using precomputed warp meshes
02602    */
02603   if (drawimage) {
02604     glBindTexture(GL_TEXTURE_2D, fb->tex);
02605     glEnable(GL_TEXTURE_2D);
02606 
02607     /* if chromatic abberation correction is enabled, use the RGB meshes */
02608     if (chromcorr) {
02609       glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE);
02610       hmd_draw_eye_texquads(dm1,  0, wsx, wsy, warp->Rxcrds, warp->Rycrds);
02611       hmd_draw_eye_texquads(dm1, hw, wsx, wsy, warp->Rxcrds, warp->Rycrds);
02612       glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE);
02613       hmd_draw_eye_texquads(dm1,  0, wsx, wsy, warp->Gxcrds, warp->Gycrds);
02614       hmd_draw_eye_texquads(dm1, hw, wsx, wsy, warp->Gxcrds, warp->Gycrds);
02615       glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE);
02616       hmd_draw_eye_texquads(dm1,  0, wsx, wsy, warp->Bxcrds, warp->Bycrds);
02617       hmd_draw_eye_texquads(dm1, hw, wsx, wsy, warp->Bxcrds, warp->Bycrds);
02618       glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
02619     } else {
02620       hmd_draw_eye_texquads(dm1,  0, wsx, wsy, warp->xcrds, warp->ycrds);
02621       hmd_draw_eye_texquads(dm1, hw, wsx, wsy, warp->xcrds, warp->ycrds);
02622     }
02623   } 
02624   glDisable(GL_TEXTURE_2D);
02625 
02626   /*
02627    * draw warp mesh grid lines over the top of the eye images if requested
02628    */
02629   if (drawlines) {
02630     /* if chromatic abberation correction is enabled, use the RGB meshes */
02631     if (chromcorr) {
02632       glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE);
02633       hmd_draw_eye_lines(dm1,  0, wsx, wsy, warp->Rxcrds, warp->Rycrds);
02634       hmd_draw_eye_lines(dm1, hw, wsx, wsy, warp->Rxcrds, warp->Rycrds);
02635       glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE);
02636       hmd_draw_eye_lines(dm1,  0, wsx, wsy, warp->Gxcrds, warp->Gycrds);
02637       hmd_draw_eye_lines(dm1, hw, wsx, wsy, warp->Gxcrds, warp->Gycrds);
02638       glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE);
02639       hmd_draw_eye_lines(dm1,  0, wsx, wsy, warp->Bxcrds, warp->Bycrds);
02640       hmd_draw_eye_lines(dm1, hw, wsx, wsy, warp->Bxcrds, warp->Bycrds);
02641       glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
02642     } else {
02643       hmd_draw_eye_lines(dm1,  0, wsx, wsy, warp->xcrds, warp->ycrds);
02644       hmd_draw_eye_lines(dm1, hw, wsx, wsy, warp->xcrds, warp->ycrds);
02645     }
02646   }
02647 
02648   return GLWIN_SUCCESS;
02649 }
02650 
02651 
02652 
02653 
02654 /*
02655  * GLSL support routines
02656  */
02657 
02658 static void glwin_print_glsl_infolog(void *voidhandle, GLhandleARB obj, 
02659                                      const char *msg) {
02660   oglhandle *handle = (oglhandle *) voidhandle;
02661   if (handle == NULL)
02662     return;
02663   glwin_ext_fctns *ext = handle->ext;
02664 
02665   GLint blen = 0;   /* length of buffer to allocate      */
02666   GLint slen = 0;   /* strlen actually written to buffer */
02667   GLcharARB *infoLog;
02668 
02669   GLGETOBJECTPARAMETERIVARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB , &blen);
02670   if (blen > 1) {
02671     if ((infoLog = (GLcharARB *) calloc(1, blen)) == NULL) {
02672       printf("GLSL shader compiler could not allocate InfoLog buffer\n");
02673       return;
02674     }
02675 
02676     GLGETINFOLOGARB(obj, blen, &slen, infoLog);
02677     printf("  %s\n", msg);
02678     printf("    %s\n", (char *) infoLog);
02679     free(infoLog);
02680   }
02681 }
02682 
02683 
02684 static int glwin_compile_shaders(void *voidhandle, glsl_shader *sh, 
02685                                  const GLubyte *vertexShader, 
02686                                  const GLubyte *fragmentShader,
02687                                  int verbose) {
02688   oglhandle *handle = (oglhandle *) voidhandle;
02689   glwin_ext_fctns *ext = handle->ext;
02690 
02691   GLint  vert_compiled = 0;
02692   GLint  frag_compiled = 0;
02693   GLint shaders_linked = 0;
02694   GLint length;
02695 
02696   /* clear shader structure before proceeding */ 
02697   memset(sh, 0, sizeof(glsl_shader));
02698  
02699   /* bail out if we don't have valid pointers for shader source code */
02700   if (vertexShader == NULL || fragmentShader == NULL) {
02701     return GLWIN_ERROR;
02702   }
02703 
02704   /* Hand the source code strings to OpenGL. */
02705   length = strlen((const char *) vertexShader);
02706   GLSHADERSOURCEARB(sh->VertexShaderObject, 1, (const char **) &vertexShader, &length);
02707 
02708   length = strlen((const char *) fragmentShader);
02709   GLSHADERSOURCEARB(sh->FragmentShaderObject, 1, (const char **) &fragmentShader, &length);
02710 
02711   /* Compile the vertex and fragment shader, and print out */
02712   /* the compiler log file if one is available.            */
02713   GLCOMPILESHADERARB(sh->VertexShaderObject);
02714   GLGETOBJECTPARAMETERIVARB(sh->VertexShaderObject,
02715                             GL_OBJECT_COMPILE_STATUS_ARB, &vert_compiled);
02716 
02717   if (verbose)
02718     glwin_print_glsl_infolog(voidhandle, sh->VertexShaderObject, "OpenGL vertex shader compilation log: ");
02719 
02720   GLCOMPILESHADERARB(sh->FragmentShaderObject);
02721   GLGETOBJECTPARAMETERIVARB(sh->FragmentShaderObject,
02722                   GL_OBJECT_COMPILE_STATUS_ARB, &frag_compiled);
02723 
02724   if (verbose)
02725     glwin_print_glsl_infolog(voidhandle, sh->FragmentShaderObject, "OpenGL fragment shader compilation log: ");
02726 
02727   if (vert_compiled && frag_compiled) {
02728     /* Populate the program object with the two compiled shaders */
02729     GLATTACHOBJECTARB(sh->ProgramObject, sh->VertexShaderObject);
02730     GLATTACHOBJECTARB(sh->ProgramObject, sh->FragmentShaderObject);
02731 
02732     /* Link the whole thing together and print out the linker log file */
02733     GLLINKPROGRAMARB(sh->ProgramObject);
02734     GLGETOBJECTPARAMETERIVARB(sh->ProgramObject, GL_OBJECT_LINK_STATUS_ARB, &shaders_linked);
02735 
02736     if (verbose)
02737       glwin_print_glsl_infolog(voidhandle, sh->ProgramObject, "OpenGL shader linkage log: " );
02738   }
02739 
02740   /* We want the shaders to go away as soon as they are detached from   */
02741   /* the program object (or program objects) they are attached to. We   */
02742   /* can simply call delete now to achieve that. Note that calling      */
02743   /* delete on a program object will result in all shaders attached to  */
02744   /* that program object to be detached. If delete has been called for  */
02745   /* these shaders, calling delete on the program object will result in */
02746   /* the shaders being deleted as well.                                 */
02747   if (vert_compiled)
02748     GLDELETEOBJECTARB(sh->VertexShaderObject);
02749   if (frag_compiled)
02750     GLDELETEOBJECTARB(sh->FragmentShaderObject);
02751 
02752   if (vert_compiled && frag_compiled && shaders_linked) {
02753     sh->isvalid = 1;
02754     return GLWIN_SUCCESS;
02755   } else {
02756     memset(sh, 0, sizeof(glsl_shader));
02757     return GLWIN_ERROR;
02758   }
02759 }
02760 
02761 
02762 int glwin_destroy_shaders(void *voidhandle, glsl_shader *sh) {
02763   oglhandle *handle = (oglhandle *) voidhandle;
02764   glwin_ext_fctns *ext = handle->ext;
02765  
02766   /* destroy the GLSL shaders and associated state */
02767   if (sh->isvalid) {
02768     GLDELETEOBJECTARB(sh->ProgramObject);
02769     memset(sh, 0, sizeof(glsl_shader));
02770 
02771     return GLWIN_SUCCESS;
02772   }
02773 
02774   return GLWIN_ERROR;
02775 }
02776 
02777 
02778 /*
02779  * GLSL vertex and fragment shaders for HMD rendering
02780  */
02781 const char *hmd_vert = 
02782   "// requires GLSL version 1.10                                           \n"
02783   "#version 110                                                            \n"
02784   "                                                                        \n"
02785   "                                                                        \n"
02786   "                                                                        \n"
02787   "void main(void) {                                                       \n"
02788   "  // transform vertex to Eye space for user clipping plane calculations \n"
02789   "  vec4 ecpos = gl_ModelViewMatrix * gl_Vertex;                          \n"
02790   "  gl_ClipVertex = ecpos;                                                \n"
02791   "                                                                        \n"
02792   "  // transform, normalize, and output normal.                           \n"
02793   "  oglnormal = normalize(gl_NormalMatrix * gl_Normal);                   \n"
02794   "                                                                        \n"
02795   "  // pass along vertex color for use fragment shading,                  \n"
02796   "  // fragment shader will get an interpolated color.                    \n"
02797   "  oglcolor = vec3(gl_Color);                                            \n"
02798   "                                                                        \n"
02799   "                                                                        \n"
02800 #if 1
02801   "  gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;               \n"
02802 #else
02803   "  gl_Position = ftransform();                                           \n"
02804 #endif
02805   "                                                                        \n"
02806   "                                                                        \n"
02807   "                                                                        \n"
02808   "                                                                        \n"
02809   "}                                                                       \n"
02810   "                                                                        \n";
02811 
02812 
02813 const char *hmd_frag = 
02814   "                                                                        \n"
02815   "                                                                        \n"
02816   "                                                                        \n"
02817   "                                                                        \n"
02818   "void main(void) {                                                       \n"
02819   "                                                                        \n"
02820 #if 1
02821   "  // Flip the surface normal if it is facing away from the viewer,      \n"
02822   "  // determined by polygon winding order provided by OpenGL.            \n"
02823   "  vec3 N = normalize(oglnormal);                                        \n"
02824   "  if (!gl_FrontFacing) {                                                \n"
02825   "    N = -N;                                                             \n"
02826   "  }                                                                     \n"
02827 #endif
02828   "                                                                        \n"
02829   "                                                                        \n"
02830   "                                                                        \n"
02831   "                                                                        \n"
02832   "                                                                        \n"
02833   "                                                                        \n"
02834   "}                                                                       \n"
02835   "                                                                        \n";
02836 
02837 
02838 int glwin_compile_hmd_shaders(void *voidhandle, glsl_shader *sh) {
02839   int rc = glwin_compile_shaders(voidhandle, sh, 
02840                                  (GLubyte *) hmd_vert, (GLubyte *) hmd_frag, 1);
02841   return rc;
02842 }
02843 
02844 #endif
02845 
02846 
02847 void glwin_draw_image(void * voidhandle, int ixs, int iys, unsigned char * img) {
02848   glRasterPos2i(0, 0);
02849   glDrawPixels(ixs, iys, GL_RGB, GL_UNSIGNED_BYTE, img);
02850   glwin_swap_buffers(voidhandle);
02851 }
02852 
02853 
02854 void glwin_draw_image_rgb3u(void *voidhandle, int stereomode, int ixs, int iys,
02855                             const unsigned char *rgb3u) {
02856   int wxs=0, wys=0;
02857   glwin_get_winsize(voidhandle, &wxs, &wys);
02858   glViewport(0, 0, wxs, wys);
02859 
02860   glDrawBuffer(GL_BACK);
02861   glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
02862   glClearColor(0.0, 0.0, 0.0, 1.0); /* black */
02863   glClear(GL_COLOR_BUFFER_BIT);
02864 
02865   glShadeModel(GL_FLAT);
02866   glMatrixMode(GL_PROJECTION);
02867   glLoadIdentity();
02868   glOrtho(0.0, wxs, 0.0, wys, -1.0, 1.0);
02869   glMatrixMode(GL_MODELVIEW);
02870   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
02871   glPixelZoom(1.0, 1.0);
02872 
02873   if (stereomode == GLWIN_STEREO_OVERUNDER) {
02874     /* printf("wsz: %dx%d  bsz: %dx%d\n", wxs, wys, ixs, iys); */
02875     const unsigned char *leftimg = rgb3u;
02876     const unsigned char *rightimg = leftimg + ((ixs * (iys/2)) * 4);
02877 
02878     glDrawBuffer(GL_BACK_LEFT);
02879     glRasterPos2i(0, 0);
02880 #if 0
02881     glColorMask(GL_TRUE, GL_TRUE, GL_FALSE, GL_TRUE); /* anaglyph or testing */
02882 #endif
02883     glDrawPixels(ixs, iys/2, GL_RGBA, GL_UNSIGNED_BYTE, leftimg);
02884 
02885     glDrawBuffer(GL_BACK_RIGHT);
02886     glRasterPos2i(0, 0);
02887 #if 0
02888     glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE); /* anaglyph or testing */
02889 #endif
02890     glDrawPixels(ixs, iys/2, GL_RGBA, GL_UNSIGNED_BYTE, rightimg);
02891   } else {
02892     glRasterPos2i(0, 0);
02893     glDrawPixels(ixs, iys, GL_RGBA, GL_UNSIGNED_BYTE, rgb3u);
02894   }
02895 
02896   glwin_swap_buffers(voidhandle);
02897 }
02898 
02899 
02900 void glwin_draw_image_tex_rgb3u(void *voidhandle, 
02901                                 int stereomode, int ixs, int iys,
02902                                 const unsigned char *rgb3u) {
02903   int wxs=0, wys=0;
02904   glwin_get_winsize(voidhandle, &wxs, &wys);
02905   glViewport(0, 0, wxs, wys);
02906 
02907   glDrawBuffer(GL_BACK);
02908   glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
02909   glClearColor(0.0, 0.0, 0.0, 1.0); /* black */
02910   glClear(GL_COLOR_BUFFER_BIT);
02911 
02912   glShadeModel(GL_FLAT);
02913   glMatrixMode(GL_PROJECTION);
02914   glLoadIdentity();
02915   glOrtho(0.0, wxs, 0.0, wys, -1.0, 1.0);
02916   glMatrixMode(GL_MODELVIEW);
02917 
02918   GLuint texName = 0;
02919   GLfloat texborder[4] = {0.0, 0.0, 0.0, 1.0};
02920   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
02921   glBindTexture(GL_TEXTURE_2D, texName);
02922 
02923   /* black borders if we go rendering anything beyond texture coordinates */
02924   glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, texborder);
02925 #if defined(GL_CLAMP_TO_BORDER)
02926   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
02927   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
02928 #else
02929   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
02930   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
02931 #endif
02932 
02933   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
02934   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
02935   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
02936 
02937   glLoadIdentity();
02938   glColor3f(1.0, 1.0, 1.0);
02939 
02940   if (stereomode == GLWIN_STEREO_OVERUNDER) {
02941     const unsigned char *leftimg = rgb3u;
02942     const unsigned char *rightimg = leftimg + ((ixs * (iys/2)) * 4);
02943 
02944     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ixs, iys, 0,
02945                  GL_RGBA, GL_UNSIGNED_BYTE, leftimg);
02946     glEnable(GL_TEXTURE_2D);
02947 
02948     glDrawBuffer(GL_BACK_LEFT);
02949 #if 0
02950     glColorMask(GL_TRUE, GL_TRUE, GL_FALSE, GL_TRUE); /* anaglyph or testing */
02951 #endif
02952     glBegin(GL_QUADS);
02953     glTexCoord2f(0.0f, 0.0f);
02954     glVertex2f(0.0f, 0.0f);
02955     glTexCoord2f(0.0f, 0.5f);
02956     glVertex2f(0.0f, wys);
02957     glTexCoord2f(1.0f, 0.5f);
02958     glVertex2f(wxs, wys);
02959     glTexCoord2f(1.0f, 0.0f);
02960     glVertex2f(wxs, 0.0f);
02961     glEnd();
02962 
02963     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ixs, iys, 0,
02964                  GL_RGBA, GL_UNSIGNED_BYTE, rightimg);
02965     glEnable(GL_TEXTURE_2D);
02966 
02967     glDrawBuffer(GL_BACK_RIGHT);
02968 #if 0
02969     glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE); /* anaglyph or testing */
02970 #endif
02971     glBegin(GL_QUADS);
02972     glTexCoord2f(0.0f, 0.5f);
02973     glVertex2f(0.0f, 0.0f);
02974     glTexCoord2f(0.0f, 1.0f);
02975     glVertex2f(0.0f, wys);
02976     glTexCoord2f(1.0f, 1.0f);
02977     glVertex2f(wxs, wys);
02978     glTexCoord2f(1.0f, 0.5f);
02979     glVertex2f(wxs, 0.0f);
02980     glEnd();
02981   } else {
02982     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ixs, iys, 0,
02983                  GL_RGBA, GL_UNSIGNED_BYTE, rgb3u);
02984     glEnable(GL_TEXTURE_2D);
02985 
02986     glBegin(GL_QUADS);
02987     glTexCoord2f(0.0f, 0.0f);
02988     glVertex2f(0.0f, 0.0f);
02989     glTexCoord2f(0.0f, 1.0f);
02990     glVertex2f(0.0f, wys);
02991     glTexCoord2f(1.0f, 1.0f);
02992     glVertex2f(wxs, wys);
02993     glTexCoord2f(1.0f, 0.0f);
02994     glVertex2f(wxs, 0.0f);
02995     glEnd();
02996   }
02997 
02998   glDisable(GL_TEXTURE_2D);
02999 
03000   glwin_swap_buffers(voidhandle);
03001 }
03002 
03003 
03004 /*
03005  * OpenGL texture mapped sphere rendering code needed for
03006  * display of spheremap textures w/ HMDs.
03007  * The texture must wraparound in the X/longitudinal dimension 
03008  * for the sphere to be drawn correctly.
03009  * The texture Y/latitude dimension doesn't have to wrap and this
03010  * code allows a single texture containing multiple images to be used
03011  * for drawing multiple spheres by offsetting the txlatstart/txlatend.
03012  */
03013 #define SPHEREMAXRES 64
03014 void glwin_draw_sphere_tex(float rad, int res, float txlatstart, float txlatend) {
03015   int i, j;
03016   float zLo, zHi, res_1;
03017   
03018   float sinLong[SPHEREMAXRES];
03019   float cosLong[SPHEREMAXRES];
03020   float sinLatVert[SPHEREMAXRES];
03021   float cosLatVert[SPHEREMAXRES];
03022   float sinLatNorm[SPHEREMAXRES];
03023   float cosLatNorm[SPHEREMAXRES];
03024   float texLat[SPHEREMAXRES];
03025   float texLong[SPHEREMAXRES];
03026 
03027   /* compute length of texture from start */
03028   float txlatsz = txlatend - txlatstart;
03029 
03030   if (res < 2)
03031     res = 2;
03032 
03033   if (res >= SPHEREMAXRES)
03034     res = SPHEREMAXRES-1;
03035 
03036   res_1 = 1.0f / res;
03037   
03038   /* longitudinal "slices" */
03039   float ang_twopi_res = 6.28318530718f * res_1;
03040   for (i=0; i<res; i++) {
03041     float angle = i * ang_twopi_res;
03042     sinLong[i] = sinf(angle);
03043     cosLong[i] = cosf(angle);
03044     texLong[i] = (res-i) * res_1;
03045   }
03046   /* ensure that longitude end point exactly matches start */
03047   sinLong[res] = 0.0f; /* sinLong[0]; */
03048   cosLong[res] = 1.0f; /* cosLong[0]; */
03049   texLong[res] = 0.0f;
03050 
03051   /* latitude "stacks" */
03052   float ang_pi_res = 3.14159265359f * res_1;
03053   for (i=0; i<=res; i++) {
03054       float angle = i * ang_pi_res;
03055     sinLatNorm[i] = sinf(angle);
03056     cosLatNorm[i] = cosf(angle);
03057     sinLatVert[i] = rad * sinLatNorm[i];
03058     cosLatVert[i] = rad * cosLatNorm[i];
03059         texLat[i] = txlatstart + (i * res_1 * txlatsz);
03060   }
03061   /* ensure top and bottom poles come to points */
03062   sinLatVert[0] = 0;
03063   sinLatVert[res] = 0;
03064 
03065   for (j=0; j<res; j++) {
03066     zLo = cosLatVert[j];
03067     zHi = cosLatVert[j+1];
03068 
03069     float stv1 = sinLatVert[j];
03070     float stv2 = sinLatVert[j+1];
03071 
03072     float stn1 = sinLatNorm[j];
03073     float ctn1 = cosLatNorm[j];
03074     float stn2 = sinLatNorm[j+1];
03075     float ctn2 = cosLatNorm[j+1];
03076 
03077     glBegin(GL_QUAD_STRIP);
03078     for (i=0; i<=res; i++) {
03079       glNormal3f(sinLong[i] * stn2, cosLong[i] * stn2, ctn2);
03080       glTexCoord2f(texLong[i], texLat[j+1]);
03081       glVertex3f(stv2 * sinLong[i], stv2 * cosLong[i], zHi);
03082 
03083       glNormal3f(sinLong[i] * stn1, cosLong[i] * stn1, ctn1);
03084       glTexCoord2f(texLong[i], texLat[j]);
03085       glVertex3f(stv1 * sinLong[i], stv1 * cosLong[i], zLo);
03086     }
03087     glEnd();
03088   }
03089 }
03090 
03091 
03092 void glwin_spheremap_draw_prepare(void *voidhandle) {
03093   glShadeModel(GL_FLAT);
03094   glDepthFunc(GL_LEQUAL);
03095   glEnable(GL_DEPTH_TEST);    /* use Z-buffer for hidden-surface removal */
03096   glClearDepth(1.0);
03097 
03098   glDrawBuffer(GL_BACK);
03099   glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
03100   glClearColor(0.0, 0.0, 0.0, 1.0); /* black */
03101   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
03102 
03103   GLuint texName = 0;
03104   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
03105   glBindTexture(GL_TEXTURE_2D, texName);
03106 
03107   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
03108 #if !(defined(WIN32) || defined(_WIN64))
03109   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
03110 #else
03111   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
03112 #endif
03113 
03114   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
03115   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
03116 
03117   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
03118 }
03119 
03120 
03121 void glwin_spheremap_upload_tex_rgb3u(void *voidhandle, int ixs, int iys,
03122                                       const unsigned char *rgb3u) {
03123   glDisable(GL_TEXTURE_2D);
03124   GLuint texName = 0;
03125   glBindTexture(GL_TEXTURE_2D, texName);
03126   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ixs, iys, 0,
03127                GL_RGBA, GL_UNSIGNED_BYTE, rgb3u);
03128   glEnable(GL_TEXTURE_2D);
03129 }
03130 
03131 
03132 void glwin_spheremap_draw_tex(void *voidhandle, int stereomode, 
03133                               int ixs, int iys, const float *hmdquat,
03134                               float fov, float rad, int res) {
03135   int wxs=0, wys=0;
03136   float n, f, a, t, b, r, l;
03137 
03138   glwin_get_winsize(voidhandle, &wxs, &wys);
03139   glViewport(0, 0, wxs, wys); /* clear entire window prior to rendering */
03140 
03141   glDrawBuffer(GL_BACK);
03142   glClearColor(0.0, 0.0, 0.0, 1.0); /* black */
03143   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
03144 
03145   glMatrixMode(GL_PROJECTION);
03146   glLoadIdentity();
03147 
03148   n = 1.0f;      /* near clipping plane */
03149   f = 15.0f;     /* far clipping plane  */
03150   a = wxs / ((float) wys); /* window aspect ratio */
03151   t = n * tanf(fov * 3.14159265359f / (180.0f*2.0f)); /* top */
03152   b = -t;        /* bottom */
03153   r = a * t;     /* right */
03154   l = -r;        /* left */
03155   glFrustum(l, r, b, t, n, f);
03156  
03157   glMatrixMode(GL_MODELVIEW);
03158   glLoadIdentity();
03159 
03160   if (hmdquat != NULL) {
03161     float hmdmat[16];
03162     quat_rot_matrix(hmdmat, hmdquat);
03163     glMultMatrixf(hmdmat);
03164   }
03165 
03166   glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
03167   glColor3f(1.0, 1.0, 1.0);
03168 
03169   /* window dims control viewport size, image dims control tex size, */
03170   /* since we will render from a spheremap that has different dims   */
03171   /* than the target window                                          */
03172   if (stereomode == GLWIN_STEREO_OVERUNDER) {
03173     /* right image is stored first */
03174     glViewport(wxs/2, 0, wxs/2, wys);
03175     glwin_draw_sphere_tex(rad, res, 0.0f, 0.5f);
03176 
03177     /* left image is stored second */
03178     glViewport(0, 0, wxs/2, wys);
03179     glwin_draw_sphere_tex(rad, res, 0.5f, 1.0f);
03180   } else {
03181     glwin_draw_sphere_tex(rad, res, 0.0f, 1.0f);
03182   }
03183 }
03184 
03185 
03186 int glwin_get_wininfo(void * voidhandle, int *instereo, int *havestencil) {
03187   oglhandle * handle = (oglhandle *) voidhandle;
03188   if (handle == NULL)
03189     return -1;
03190 
03191   if (instereo != NULL)
03192     *instereo = handle->instereo;
03193 
03194   if (havestencil != NULL)
03195     *havestencil = handle->havestencil;
03196 
03197   return 0;
03198 }
03199 
03200 
03201 int glwin_get_winsize(void * voidhandle, int *xsize, int *ysize) {
03202   oglhandle * handle = (oglhandle *) voidhandle;
03203   if (handle == NULL)
03204     return -1;
03205 
03206 #if 0
03207   if (handle) { 
03208     /* check window size */
03209     XWindowAttributes xwa;
03210     XGetWindowAttributes(handle->dpy, handle->win, &xwa);
03211     handle->width = xwa.width;
03212     handle->height = xwa.height;
03213   }
03214 #endif
03215 
03216   if (xsize != NULL)
03217     *xsize = handle->width;
03218 
03219   if (ysize != NULL)
03220     *ysize = handle->height;
03221 
03222   return 0;
03223 }
03224 
03225 
03226 int glwin_get_winpos(void * voidhandle, int *xpos, int *ypos) {
03227   oglhandle * handle = (oglhandle *) voidhandle;
03228   if (handle == NULL)
03229     return -1;
03230 
03231   if (xpos != NULL)
03232     *xpos = handle->xpos;
03233 
03234   if (ypos != NULL)
03235     *ypos = handle->ypos;
03236 
03237   return 0;
03238 }
03239 
03240 
03241 int glwin_get_mousepointer(void *voidhandle, int *x, int *y) {
03242   oglhandle * handle = (oglhandle *) voidhandle;
03243   if (handle == NULL)
03244     return -1;
03245 
03246   if (x != NULL)
03247     *x = handle->mousex;
03248 
03249   if (y != NULL)
03250     *y = handle->mousey;
03251 
03252   return 0;
03253 }
03254 
03255 
03256 int glwin_get_lastevent(void * voidhandle, int *evdev, int *evval, char *evkey) {
03257   oglhandle * handle = (oglhandle *) voidhandle;
03258   if (handle == NULL)
03259     return -1;
03260 
03261   if (evdev != NULL)
03262     *evdev = handle->evdev;
03263 
03264   if (evval != NULL)
03265     *evval = handle->evval;
03266 
03267   if (evkey != NULL)
03268     *evkey = handle->evkey;
03269 
03270   return 0;
03271 }
03272 
03273 
03274 int glwin_spaceball_available(void *voidhandle) {
03275   oglhandle * handle = (oglhandle *) voidhandle;
03276 
03277   /* check to see if we have a spaceball attached */
03278   if (handle->sball != NULL)
03279     return 1;
03280 
03281   return 0;
03282 }
03283 
03284 
03285 int glwin_get_spaceball(void *voidhandle, int *rx, int *ry, int *rz, int *tx, int *ty, int *tz, int *buttons) {
03286   oglhandle * handle = (oglhandle *) voidhandle;
03287   if (handle == NULL)
03288     return 0;
03289 
03290   if ((handle->sball != NULL) && (handle->sballevent.event == 1)) {
03291     *rx = handle->sballevent.rx;
03292     *ry = handle->sballevent.ry;
03293     *rz = handle->sballevent.rz;
03294     *tx = handle->sballevent.tx;
03295     *ty = handle->sballevent.ty;
03296     *tz = handle->sballevent.tz;
03297     *buttons = handle->sballevent.buttons;
03298     return 1;
03299   }
03300 
03301   return 0;
03302 }
03303 
03304 
03305 #else
03306 
03307 
03308 /* 
03309  * stub code to allow linkage
03310  */
03311 void * glwin_create(const char * wintitle, int width, int height) {
03312   return NULL;
03313 }
03314 
03315 void glwin_destroy(void * voidhandle) {
03316   return;
03317 }
03318 
03319 void glwin_swap_buffers(void * voidhandle) {
03320   return;
03321 }
03322 
03323 int glwin_handle_events(void * voidhandle, int evblockmode) {
03324   return 0;
03325 }
03326 
03327 int glwin_get_wininfo(void * voidhandle, int *instereo, int *havestencil) {
03328   return -1;
03329 }
03330 
03331 int glwin_get_winsize(void * voidhandle, int *xsize, int *ysize) {
03332   return -1;
03333 }
03334 
03335 int glwin_get_winpos(void * voidhandle, int *xpos, int *ypos) {
03336   return -1;
03337 }
03338 
03339 int glwin_get_mousepointer(void *voidhandle, int *x, int *y) {
03340   return -1;
03341 }
03342 
03343 int glwin_get_lastevent(void * voidhandle, int *evdev, int *evval, char *evkey) {
03344   return -1;
03345 }
03346 
03347 int glwin_query_extension(const char *extname) {
03348   return 0;
03349 }
03350 
03351 int glwin_query_vsync(void *voidhandle, int *onoff) {
03352   return GLWIN_NOT_IMPLEMENTED;
03353 }
03354 
03355 void glwin_draw_image(void * voidhandle, int xsize, int ysize, unsigned char * img) {
03356   return;
03357 }
03358 
03359 void glwin_draw_image_rgb3u(void *voidhandle, int stereomode, int ixs, int iys,
03360                             const unsigned char *rgb3u) {
03361   return;
03362 }
03363 
03364 void glwin_draw_image_tex_rgb3u(void *voidhandle, 
03365                                 int stereomode, int ixs, int iys,
03366                                 const unsigned char *rgb3u) {
03367   return;
03368 }
03369 
03370 void glwin_spheremap_draw_prepare(void *voidhandle) {
03371   return;
03372 }
03373 
03374 void glwin_spheremap_upload_tex_rgb3u(void *voidhandle, int ixs, int iys,
03375                                       const unsigned char *rgb3u) {
03376   return;
03377 }
03378 
03379 void glwin_draw_sphere_tex(float rad, int res, float txlatstart, float txlatend) {
03380   return;
03381 }
03382 
03383 void glwin_spheremap_draw(void *voidhandle, int stereomode, int ixs, int iys,
03384                           const float *hmdquat, float fov, float rad, int res) {
03385   return;
03386 }
03387 
03388 int glwin_resize(void *voidhandle, int width, int height) {
03389   return -1;
03390 }
03391 
03392 int glwin_reposition(void *voidhandle, int xpos, int ypos) {
03393   return -1;
03394 }
03395 
03396 int glwin_fullscreen(void * voidhandle, int fson, int xinescreen) {
03397   return -1;
03398 }  
03399 
03400 int glwin_spaceball_available(void *voidhandle) {
03401   return 0;
03402 }
03403 
03404 int glwin_get_spaceball(void *voidhandle, int *rx, int *ry, int *rz, int *tx, int *ty, int *tz, int *buttons) {
03405   return 0;
03406 }
03407 
03408 #endif
03409 

Generated on Sat Apr 20 02:42:48 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002