Home | History | Annotate | Line # | Download | only in glx
      1 
      2 /* Copyright (c) Mark J. Kilgard, 1994, 1997. */
      3 
      4 /* This program is freely distributable without licensing fees
      5    and is provided without guarantee or warrantee expressed or
      6    implied. This program is -not- in the public domain. */
      7 
      8 #ifdef __VMS
      9 #include <GL/vms_x_fix.h>
     10 #endif
     11 
     12 #include <stdlib.h>
     13 #include <string.h>
     14 #include <stdio.h>
     15 
     16 #if !defined(_WIN32)
     17 #include <X11/Xlib.h>
     18 #endif
     19 
     20 /* SGI optimization introduced in IRIX 6.3 to avoid X server
     21    round trips for interning common X atoms. */
     22 #if defined(_SGI_EXTRA_PREDEFINES) && !defined(NO_FAST_ATOMS)
     23 #include <X11/SGIFastAtom.h>
     24 #else
     25 #define XSGIFastInternAtom(dpy,string,fast_name,how) XInternAtom(dpy,string,how)
     26 #endif
     27 
     28 #include "glutint.h"
     29 
     30 /* GLUT inter-file variables */
     31 /* *INDENT-OFF* */
     32 char *__glutProgramName = NULL;
     33 int __glutArgc = 0;
     34 char **__glutArgv = NULL;
     35 char *__glutGeometry = NULL;
     36 Display *__glutDisplay = NULL;
     37 int __glutScreen;
     38 Window __glutRoot;
     39 int __glutScreenHeight;
     40 int __glutScreenWidth;
     41 GLboolean __glutIconic = GL_FALSE;
     42 GLboolean __glutDebug = GL_FALSE;
     43 unsigned int __glutDisplayMode =
     44   GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH;
     45 char *__glutDisplayString = NULL;
     46 int __glutConnectionFD;
     47 XSizeHints __glutSizeHints = {0};
     48 int __glutInitWidth = 300, __glutInitHeight = 300;
     49 int __glutInitX = -1, __glutInitY = -1;
     50 GLboolean __glutForceDirect = GL_FALSE,
     51   __glutTryDirect = GL_TRUE;
     52 Atom __glutWMDeleteWindow;
     53 char *__glutPPMFile = NULL;
     54 /* *INDENT-ON* */
     55 
     56 #ifdef _WIN32
     57 void (__cdecl *__glutExitFunc)(int retval) = NULL;
     58 #endif
     59 
     60 static Bool synchronize = False;
     61 
     62 #if defined(_WIN32)
     63 
     64 #ifdef __BORLANDC__
     65 #include <float.h>  /* For masking floating point exceptions. */
     66 #endif
     67 
     68 void
     69 __glutOpenWin32Connection(char* display)
     70 {
     71   static char *classname;
     72   WNDCLASS  wc;
     73   HINSTANCE hInstance = GetModuleHandle(NULL);
     74 
     75   /* Make sure we register the window only once. */
     76   if(classname)
     77     return;
     78 
     79 #ifdef __BORLANDC__
     80   /* Under certain conditions (e.g. while rendering solid surfaces with
     81      lighting enabled) Microsoft OpenGL libraries cause some illegal
     82      operations like floating point overflow or division by zero. The
     83      default behaviour of Microsoft compilers is to mask (ignore)
     84      floating point exceptions, while Borland compilers do not.  The
     85      following function of Borland RTL allows to mask exceptions.
     86      Advice from Pier Giorgio Esposito (mc2172 (at) mclink.it). */
     87   _control87(MCW_EM,MCW_EM);
     88 #endif
     89 
     90   classname = "GLUT";
     91 
     92   /* Clear (important!) and then fill in the window class structure. */
     93   memset(&wc, 0, sizeof(WNDCLASS));
     94   wc.style         = CS_OWNDC;
     95   wc.lpfnWndProc   = (WNDPROC)__glutWindowProc;
     96   wc.hInstance     = hInstance;
     97   wc.hIcon         = LoadIcon(hInstance, "GLUT_ICON");
     98   wc.hCursor       = LoadCursor(hInstance, IDC_ARROW);
     99   wc.hbrBackground = NULL;
    100   wc.lpszMenuName  = NULL;
    101   wc.lpszClassName = classname;
    102 
    103   /* Fill in a default icon if one isn't specified as a resource. */
    104   if(!wc.hIcon)
    105     wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
    106 
    107   if(!RegisterClass(&wc)) {
    108     __glutFatalError("RegisterClass() failed:"
    109 		     "Cannot register GLUT window class.");
    110   }
    111 
    112   __glutScreenWidth     = GetSystemMetrics(SM_CXSCREEN);
    113   __glutScreenHeight    = GetSystemMetrics(SM_CYSCREEN);
    114 
    115   /* Set the root window to NULL because windows creates a top-level
    116      window when the parent is NULL.  X creates a top-level window
    117      when the parent is the root window. */
    118   __glutRoot            = NULL;
    119 
    120   /* Set the display to 1 -- we shouldn't be using this anywhere
    121      (except as an argument to X calls). */
    122   __glutDisplay         = (Display*)1;
    123 
    124   /* There isn't any concept of multiple screens in Win32, therefore,
    125      we don't need to keep track of the screen we're on... it's always
    126      the same one. */
    127   __glutScreen          = 0;
    128 }
    129 #else /* !_WIN32 */
    130 void
    131 __glutOpenXConnection(char *display)
    132 {
    133   int errorBase, eventBase;
    134 
    135   __glutDisplay = XOpenDisplay(display);
    136   if (!__glutDisplay)
    137     __glutFatalError("could not open display: %s",
    138       XDisplayName(display));
    139   if (synchronize)
    140     XSynchronize(__glutDisplay, True);
    141   if (!glXQueryExtension(__glutDisplay, &errorBase, &eventBase))
    142     __glutFatalError(
    143       "OpenGL GLX extension not supported by display: %s",
    144       XDisplayName(display));
    145   __glutScreen = DefaultScreen(__glutDisplay);
    146   __glutRoot = RootWindow(__glutDisplay, __glutScreen);
    147   __glutScreenWidth = DisplayWidth(__glutDisplay, __glutScreen);
    148   __glutScreenHeight = DisplayHeight(__glutDisplay,
    149     __glutScreen);
    150   __glutConnectionFD = ConnectionNumber(__glutDisplay);
    151   __glutWMDeleteWindow = XSGIFastInternAtom(__glutDisplay,
    152     "WM_DELETE_WINDOW", SGI_XA_WM_DELETE_WINDOW, False);
    153 }
    154 #endif /* _WIN32 */
    155 
    156 void
    157 #ifdef OLD_VMS
    158   __glutInitTime(struct timeval6 *beginning)
    159 #else
    160   __glutInitTime(struct timeval *beginning)
    161 #endif
    162 {
    163   static int beenhere = 0;
    164 #ifdef OLD_VMS
    165    static struct timeval6 genesis;
    166 #else
    167    static struct timeval genesis;
    168 #endif
    169 
    170   if (!beenhere) {
    171     GETTIMEOFDAY(&genesis);
    172     beenhere = 1;
    173   }
    174   *beginning = genesis;
    175 }
    176 
    177 static void
    178 removeArgs(int *argcp, char **argv, int numToRemove)
    179 {
    180   int i, j;
    181 
    182   for (i = 0, j = numToRemove; argv[j]; i++, j++) {
    183     argv[i] = argv[j];
    184   }
    185   argv[i] = NULL;
    186   *argcp -= numToRemove;
    187 }
    188 
    189 void GLUTAPIENTRY
    190 glutInit(int *argcp, char **argv)
    191 {
    192   char *display = NULL;
    193   char *str, *geometry = NULL;
    194 #ifdef OLD_VMS
    195    struct timeval6 unused;
    196 #else
    197    struct timeval unused;
    198 #endif
    199    int i;
    200 
    201   if (__glutDisplay) {
    202     __glutWarning("glutInit being called a second time.");
    203     return;
    204   }
    205   /* Determine temporary program name. */
    206   str = strrchr(argv[0], '/');
    207   if (str == NULL) {
    208     __glutProgramName = argv[0];
    209   } else {
    210     __glutProgramName = str + 1;
    211   }
    212 
    213   /* Make private copy of command line arguments. */
    214   __glutArgc = *argcp;
    215   __glutArgv = (char **) malloc(__glutArgc * sizeof(char *));
    216   if (!__glutArgv)
    217     __glutFatalError("out of memory.");
    218   for (i = 0; i < __glutArgc; i++) {
    219     __glutArgv[i] = __glutStrdup(argv[i]);
    220     if (!__glutArgv[i])
    221       __glutFatalError("out of memory.");
    222   }
    223 
    224   /* determine permanent program name */
    225   str = strrchr(__glutArgv[0], '/');
    226   if (str == NULL) {
    227     __glutProgramName = __glutArgv[0];
    228   } else {
    229     __glutProgramName = str + 1;
    230   }
    231 
    232   /* parse arguments for standard options */
    233   for (i = 1; i < __glutArgc; i++) {
    234     if (!strcmp(__glutArgv[i], "-display")) {
    235 #if defined(_WIN32)
    236       __glutWarning("-display option not supported by Win32 GLUT.");
    237 #endif
    238       if (++i >= __glutArgc) {
    239         __glutFatalError(
    240           "follow -display option with X display name.");
    241       }
    242       display = __glutArgv[i];
    243       removeArgs(argcp, &argv[1], 2);
    244     } else if (!strcmp(__glutArgv[i], "-geometry")) {
    245       if (++i >= __glutArgc) {
    246         __glutFatalError(
    247           "follow -geometry option with geometry parameter.");
    248       }
    249       geometry = __glutArgv[i];
    250       removeArgs(argcp, &argv[1], 2);
    251     } else if (!strcmp(__glutArgv[i], "-direct")) {
    252 #if defined(_WIN32)
    253       __glutWarning("-direct option not supported by Win32 GLUT.");
    254 #endif
    255       if (!__glutTryDirect)
    256         __glutFatalError(
    257           "cannot force both direct and indirect rendering.");
    258       __glutForceDirect = GL_TRUE;
    259       removeArgs(argcp, &argv[1], 1);
    260     } else if (!strcmp(__glutArgv[i], "-indirect")) {
    261 #if defined(_WIN32)
    262       __glutWarning("-indirect option not supported by Win32 GLUT.");
    263 #endif
    264       if (__glutForceDirect)
    265         __glutFatalError(
    266           "cannot force both direct and indirect rendering.");
    267       __glutTryDirect = GL_FALSE;
    268       removeArgs(argcp, &argv[1], 1);
    269     } else if (!strcmp(__glutArgv[i], "-iconic")) {
    270       __glutIconic = GL_TRUE;
    271       removeArgs(argcp, &argv[1], 1);
    272     } else if (!strcmp(__glutArgv[i], "-gldebug")) {
    273       __glutDebug = GL_TRUE;
    274       removeArgs(argcp, &argv[1], 1);
    275     } else if (!strcmp(__glutArgv[i], "-sync")) {
    276 #if defined(_WIN32)
    277       __glutWarning("-sync option not supported by Win32 GLUT.");
    278 #endif
    279       synchronize = GL_TRUE;
    280       removeArgs(argcp, &argv[1], 1);
    281     } else {
    282       /* Once unknown option encountered, stop command line
    283          processing. */
    284       break;
    285     }
    286   }
    287 #if defined(_WIN32)
    288   __glutOpenWin32Connection(display);
    289 #else
    290   __glutOpenXConnection(display);
    291 #endif
    292   if (geometry) {
    293     int flags, x, y, width, height;
    294 
    295     /* Fix bogus "{width|height} may be used before set"
    296        warning */
    297     width = 0;
    298     height = 0;
    299 
    300     flags = XParseGeometry(geometry, &x, &y,
    301       (unsigned int *) &width, (unsigned int *) &height);
    302     if (WidthValue & flags) {
    303       /* Careful because X does not allow zero or negative
    304          width windows */
    305       if (width > 0)
    306         __glutInitWidth = width;
    307     }
    308     if (HeightValue & flags) {
    309       /* Careful because X does not allow zero or negative
    310          height windows */
    311       if (height > 0)
    312         __glutInitHeight = height;
    313     }
    314     glutInitWindowSize(__glutInitWidth, __glutInitHeight);
    315     if (XValue & flags) {
    316       if (XNegative & flags)
    317         x = DisplayWidth(__glutDisplay, __glutScreen) +
    318           x - __glutSizeHints.width;
    319       /* Play safe: reject negative X locations */
    320       if (x >= 0)
    321         __glutInitX = x;
    322     }
    323     if (YValue & flags) {
    324       if (YNegative & flags)
    325         y = DisplayHeight(__glutDisplay, __glutScreen) +
    326           y - __glutSizeHints.height;
    327       /* Play safe: reject negative Y locations */
    328       if (y >= 0)
    329         __glutInitY = y;
    330     }
    331     glutInitWindowPosition(__glutInitX, __glutInitY);
    332   }
    333   __glutInitTime(&unused);
    334 
    335   /* check if GLUT_FPS env var is set */
    336   {
    337      const char *fps = getenv("GLUT_FPS");
    338      if (fps) {
    339         sscanf(fps, "%d", &__glutFPS);
    340         if (__glutFPS <= 0)
    341            __glutFPS = 5000;  /* 5000 milliseconds */
    342      }
    343   }
    344 
    345   /* check if GLUT_PPM_FILE env var is set */
    346   __glutPPMFile = getenv("GLUT_PPM_FILE");
    347 }
    348 
    349 #ifdef _WIN32
    350 void GLUTAPIENTRY
    351 __glutInitWithExit(int *argcp, char **argv, void (__cdecl *exitfunc)(int))
    352 {
    353   __glutExitFunc = exitfunc;
    354   glutInit(argcp, argv);
    355 }
    356 #endif
    357 
    358 /* CENTRY */
    359 void GLUTAPIENTRY
    360 glutInitWindowPosition(int x, int y)
    361 {
    362   __glutInitX = x;
    363   __glutInitY = y;
    364   if (x >= 0 && y >= 0) {
    365     __glutSizeHints.x = x;
    366     __glutSizeHints.y = y;
    367     __glutSizeHints.flags |= USPosition;
    368   } else {
    369     __glutSizeHints.flags &= ~USPosition;
    370   }
    371 }
    372 
    373 void GLUTAPIENTRY
    374 glutInitWindowSize(int width, int height)
    375 {
    376   __glutInitWidth = width;
    377   __glutInitHeight = height;
    378   if (width > 0 && height > 0) {
    379     __glutSizeHints.width = width;
    380     __glutSizeHints.height = height;
    381     __glutSizeHints.flags |= USSize;
    382   } else {
    383     __glutSizeHints.flags &= ~USSize;
    384   }
    385 }
    386 
    387 void GLUTAPIENTRY
    388 glutInitDisplayMode(unsigned int mask)
    389 {
    390   __glutDisplayMode = mask;
    391 }
    392 
    393 /* ENDCENTRY */
    394