home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / togl15.zip / togl.c < prev    next >
C/C++ Source or Header  |  2000-02-16  |  104KB  |  3,414 lines

  1. /* $Id: togl.c,v 1.45 1998/08/22 03:05:53 brianp Exp $ */
  2.  
  3. /*
  4.  * Togl - a Tk OpenGL widget
  5.  * Version 1.5
  6.  * Copyright (C) 1996-1997  Brian Paul and Ben Bederson
  7.  * See the LICENSE file for copyright details.
  8.  */
  9.  
  10.  
  11. /*
  12.  * $Log: togl.c,v $
  13.  * Revision 1.45  1998/08/22 03:05:53  brianp
  14.  * added -indirect config option
  15.  *
  16.  * Revision 1.44  1998/05/04 23:42:43  brianp
  17.  * fixed NULL pointer dereference bug in ToglCmdDeletedProc()
  18.  *
  19.  * Revision 1.43  1998/03/12 04:10:47  brianp
  20.  * added display list and OpenGL context sharing options
  21.  *
  22.  * Revision 1.42  1998/03/12 03:20:31  brianp
  23.  * fixed a few overlay update bugs (Yang Guo Liang)
  24.  *
  25.  * Revision 1.41  1998/01/20 01:05:10  brianp
  26.  * added more destroy/clean-up code
  27.  * added a few Tcl 7.4 / Tk 4.0 #if/#else/#endifs (David Laur)
  28.  *
  29.  * Revision 1.40  1997/12/13 02:27:46  brianp
  30.  * only call Tcl_DeleteCommandFromToken() is using Tcl/Tk 8.0 or later
  31.  *
  32.  * Revision 1.39  1997/12/13 02:26:02  brianp
  33.  * test for STEREO to enable SGI stereo code
  34.  * general code clean-up
  35.  *
  36.  * Revision 1.38  1997/12/11 02:21:18  brianp
  37.  * added support for Tcl/Tk 8.0p2
  38.  *
  39.  * Revision 1.37  1997/11/15 04:11:30  brianp
  40.  * added Adrian J. Chung's widget destroy code
  41.  *
  42.  * Revision 1.36  1997/11/15 03:33:13  brianp
  43.  * fixed multi-expose/redraw problem (Andy Colebourne)
  44.  *
  45.  * Revision 1.35  1997/11/15 03:28:42  brianp
  46.  * removed code in Togl_Configure(), added for stereo, that caused a new bug
  47.  *
  48.  * Revision 1.34  1997/11/15 02:58:48  brianp
  49.  * added Togl_TkWin() per Glenn Lewis
  50.  *
  51.  * Revision 1.33  1997/10/01 02:50:57  brianp
  52.  * added SGI stereo functions from Ben Evans
  53.  *
  54.  * Revision 1.32  1997/10/01 00:25:22  brianp
  55.  * made small change for HP compilation (Glenn Lewis)
  56.  *
  57.  * Revision 1.31  1997/09/17 02:41:07  brianp
  58.  * added Geza Groma's Windows NT/95 patches
  59.  *
  60.  * Revision 1.30  1997/09/12 01:21:05  brianp
  61.  * a few more tweaks for Windows compilation
  62.  */
  63.  
  64.  
  65. /*
  66.  * Currently support X11, OS2, and WIN32
  67.  */
  68. #ifndef WIN32
  69. #ifndef __EMX__
  70. #define X11
  71. #endif
  72. #endif
  73.  
  74.  
  75. /*** Windows headers ***/
  76. #ifdef WIN32
  77. #define WIN32_LEAN_AND_MEAN
  78. #include <windows.h>
  79. #undef WIN32_LEAN_AND_MEAN
  80. #include <winnt.h>
  81. #endif /* WIN32 */
  82.  
  83. /*** OS/2 headers ***/
  84. #ifdef __EMX__
  85. #define INCL_WIN
  86. #include <os2.h>
  87. #undef INCL_WIN
  88. #include <GL/pgl.h>
  89.     /* Needed for XVisualInfo? */
  90. #include <X11/Xlib.h>
  91. #include <X11/Xutil.h>
  92. #endif
  93.  
  94. /*** Standard C headers ***/
  95. #include <assert.h>
  96. #include <stdio.h>
  97. #include <stdlib.h>
  98. #include <string.h>
  99.  
  100. /*** X Window System headers ***/
  101. #ifdef X11
  102. #include <X11/Xlib.h>
  103. #include <X11/Xutil.h>
  104. #include <X11/Xatom.h>  /* for XA_RGB_DEFAULT_MAP atom */
  105. #if defined(__vms)
  106. #include <X11/StdCmap.h>  /* for XmuLookupStandardColormap */
  107. #else
  108. #include <X11/Xmu/StdCmap.h>  /* for XmuLookupStandardColormap */
  109. #endif
  110. #include <GL/glx.h>
  111. #endif /*X11*/
  112.  
  113. /*** Tcl/Tk headers ***/
  114. #ifdef X11
  115. #ifndef _TKPORT
  116. #define _TKPORT  /* This eliminates need to include a bunch of Tk baggage */
  117. #endif /* X11 */
  118. #endif
  119. #include <tcl.h>
  120. #include <tk.h>
  121. #if defined(X11)
  122. #if TK_MAJOR_VERSION==4 && TK_MINOR_VERSION==0
  123. #  include "tkInt4.0.h"
  124. #  define NO_TK_CURSOR
  125. #elif TK_MAJOR_VERSION==4 && TK_MINOR_VERSION==1
  126. #  include "tkInt4.1.h"
  127. #elif TK_MAJOR_VERSION==4 && TK_MINOR_VERSION==2
  128. #  include "tkInt4.2.h"
  129. #elif TK_MAJOR_VERSION==8 && TK_MINOR_VERSION==0 && TK_RELEASE_SERIAL==0
  130. #  include "tkInt8.0.h"
  131. #elif TK_MAJOR_VERSION==8 && TK_MINOR_VERSION==0 && TK_RELEASE_SERIAL==2
  132. #  include "tkInt8.0p2.h"
  133. #else
  134.    Sorry, you will have to edit togl.c to include the right tkInt.h file
  135. #endif
  136. #elif defined(WIN32)
  137. #if TK_MAJOR_VERSION<8
  138.    Sorry Windows version requires Tcl/Tk ver 8.0 or higher.
  139. #endif
  140. #include "tkInt.h"
  141. #include "tkWinInt.h"
  142. #elif defined(__EMX__)
  143. #if TK_MAJOR_VERSION<8
  144.    Sorry OS/2 version requires Tcl/Tk ver 8.0 or higher.
  145. #endif
  146. #ifndef _TKPORT
  147. #define _TKPORT  /* This eliminates need to include a bunch of Tk baggage */
  148. #endif
  149. #ifndef _TCLOS2INT
  150. #define _TCLOS2INT 
  151. #endif
  152. #include "tkOS2Int.h"
  153. #endif /* X11 */
  154. #include "togl.h"
  155.  
  156.  
  157.  
  158. /* Defaults */
  159. #define DEFAULT_WIDTH        "400"
  160. #define DEFAULT_HEIGHT        "400"
  161. #define DEFAULT_IDENT        ""
  162. #define DEFAULT_FONTNAME    "fixed"
  163. #define DEFAULT_TIME        "1"
  164.  
  165.  
  166. #ifdef WIN32
  167. /* maximum size of a logical palette corresponding to a colormap in color index mode */
  168. #define MAX_CI_COLORMAP_SIZE 4096
  169. #endif /* WIN32 */
  170.  
  171. #define MAX(a,b)    (((a)>(b))?(a):(b))
  172.  
  173. #define TCL_ERR(interp, string) {Tcl_ResetResult(interp);        \
  174.                      Tcl_AppendResult(interp, string, NULL);\
  175.                  return(TCL_ERROR);}
  176.  
  177. #define ALL_EVENTS_MASK \
  178.     KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask|    \
  179.     EnterWindowMask|LeaveWindowMask|PointerMotionMask|ExposureMask|    \
  180.     VisibilityChangeMask|FocusChangeMask|PropertyChangeMask|ColormapChangeMask
  181.  
  182.  
  183. struct Togl
  184. {
  185.    struct Togl *Next;           /* next in linked list */
  186.  
  187. #if defined(WIN32)
  188.    HDC tglGLHdc;                /* Device context of device that OpenGL calls will be drawn on */
  189.    HGLRC tglGLHglrc;            /* OpenGL rendering context to be made current */
  190.    int CiColormapSize;          /* (Maximum) size of colormap in color index mode */
  191. #elif defined(__EMX__)              
  192.    HGC tglGLHgc;                /* Device context of device that OpenGL calls will be drawn on */
  193.    HWND tglGLHwnd;                /* Window that OpengGL device context runs in */
  194.    HAB tglGLHab;                /* Appiclation anchor block */
  195. #elif defined(X11)
  196.    GLXContext GlCtx;        /* Normal planes GLX context */
  197. #endif /* WIN32 */
  198.    Display *display;        /* X's token for the window's display. */
  199.    Tk_Window  TkWin;        /* Tk window structure */
  200.    Tcl_Interp *Interp;        /* Tcl interpreter */
  201.    Tcl_Command widgetCmd;       /* Token for togl's widget command */
  202. #ifndef NO_TK_CURSOR
  203.    Tk_Cursor Cursor;        /* The widget's cursor */
  204. #endif
  205.    int Width, Height;        /* Dimensions of window */
  206.    int Time;            /* Time value for timer */
  207. #if (TCL_MAJOR_VERSION * 100 + TCL_MINOR_VERSION) >= 705
  208.    Tcl_TimerToken timerHandler; /* Token for togl's timer handler */
  209. #else
  210.    Tk_TimerToken timerHandler;  /* Token for togl's timer handler */
  211. #endif
  212.    int RgbaFlag;        /* configuration flags (ala GLX parameters) */
  213.    int RgbaRed;
  214.    int RgbaGreen;
  215.    int RgbaBlue;
  216.    int DoubleFlag;
  217.    int DepthFlag;
  218.    int DepthSize;
  219.    int AccumFlag;
  220.    int AccumRed;
  221.    int AccumGreen;
  222.    int AccumBlue;
  223.    int AccumAlpha;
  224.    int AlphaFlag;
  225.    int AlphaSize;
  226.    int StencilFlag;
  227.    int StencilSize;
  228.    int PrivateCmapFlag;
  229.    int OverlayFlag;
  230.    int StereoFlag;
  231.    int AuxNumber;
  232.    int Indirect;
  233.    char *ShareList;             /* name (ident) of Togl to share dlists with */
  234.    char *ShareContext;          /* name (ident) to share OpenGL context with */
  235.  
  236.    char *Ident;                /* User's identification string */
  237.    ClientData Client_Data;        /* Pointer to user data */
  238.  
  239.    GLboolean UpdatePending;        /* Should normal planes be redrawn? */
  240.  
  241.    Togl_Callback *CreateProc;        /* Callback when widget is created */
  242.    Togl_Callback *DisplayProc;        /* Callback when widget is rendered */
  243.    Togl_Callback *ReshapeProc;        /* Callback when window size changes */
  244.    Togl_Callback *DestroyProc;        /* Callback when widget is destroyed */
  245.    Togl_Callback *TimerProc;        /* Callback when widget is idle */
  246.  
  247.    /* Overlay stuff */
  248. #if defined(X11)
  249.    GLXContext OverlayCtx;        /* Overlay planes OpenGL context */
  250. #elif defined(WIN32)
  251.    HGLRC tglGLOverlayHglrc;
  252. #elif defined(__EMX__)
  253. /* :TODO: */
  254. #endif /* X11 */
  255.    Window OverlayWindow;        /* The overlay window, or 0 */
  256.    Togl_Callback *OverlayDisplayProc;    /* Overlay redraw proc */
  257.    GLboolean OverlayUpdatePending;    /* Should overlay be redrawn? */
  258.    Colormap OverlayCmap;        /* colormap for overlay is created */
  259.    int OverlayTransparentPixel;        /* transparent pixel */
  260.    int OverlayIsMapped;
  261.  
  262.    /* for DumpToEpsFile: Added by Miguel A. de Riera Pasenau 10.01.1997 */
  263.    XVisualInfo *VisInfo;        /* Visual info of the current */
  264.                     /* context needed for DumpToEpsFile */
  265.    GLfloat *EpsRedMap;        /* Index2RGB Maps for Color index modes */
  266.    GLfloat *EpsGreenMap;
  267.    GLfloat *EpsBlueMap;
  268.    GLint EpsMapSize;                /* = Number of indices in our Togl */
  269. };
  270.  
  271.  
  272. /* NTNTNT need to change to handle Windows Data Types */
  273. /*
  274.  * Prototypes for functions local to this file
  275.  */
  276. static int Togl_Cmd(ClientData clientData, Tcl_Interp *interp,
  277.                     int argc, char **argv);
  278. static void Togl_EventProc(ClientData clientData, XEvent *eventPtr);
  279. static int Togl_MakeWindowExist(struct Togl *togl);
  280. #ifdef MESA_COLOR_HACK
  281. static int get_free_color_cells( Display *display, int screen,
  282.                                  Colormap colormap);
  283. static void free_default_color_cells( Display *display, Colormap colormap);
  284. #endif
  285. static void ToglCmdDeletedProc( ClientData );
  286.  
  287.  
  288.  
  289. #if defined(__sgi) && defined(STEREO)
  290. /* SGI-only stereo */
  291. static void stereoMakeCurrent( Display *dpy, Window win, GLXContext ctx );
  292. static void stereoInit( struct Togl *togl,int stereoEnabled );
  293. #endif
  294.  
  295.  
  296.  
  297. /*
  298.  * Setup Togl widget configuration options:
  299.  */
  300.  
  301. static Tk_ConfigSpec configSpecs[] = {
  302.     {TK_CONFIG_PIXELS, "-height", "height", "Height",
  303.      DEFAULT_HEIGHT, Tk_Offset(struct Togl, Height), 0, NULL},
  304.  
  305.     {TK_CONFIG_PIXELS, "-width", "width", "Width",
  306.      DEFAULT_WIDTH, Tk_Offset(struct Togl, Width), 0, NULL},
  307.  
  308.     {TK_CONFIG_BOOLEAN, "-rgba", "rgba", "Rgba",
  309.      "true", Tk_Offset(struct Togl, RgbaFlag), 0, NULL},
  310.  
  311.     {TK_CONFIG_INT, "-redsize", "redsize", "RedSize",
  312.      "1", Tk_Offset(struct Togl, RgbaRed), 0, NULL},
  313.  
  314.     {TK_CONFIG_INT, "-greensize", "greensize", "GreenSize",
  315.      "1", Tk_Offset(struct Togl, RgbaGreen), 0, NULL},
  316.  
  317.     {TK_CONFIG_INT, "-bluesize", "bluesize", "BlueSize",
  318.      "1", Tk_Offset(struct Togl, RgbaBlue), 0, NULL},
  319.  
  320.     {TK_CONFIG_BOOLEAN, "-double", "double", "Double",
  321.      "false", Tk_Offset(struct Togl, DoubleFlag), 0, NULL},
  322.  
  323.     {TK_CONFIG_BOOLEAN, "-depth", "depth", "Depth",
  324.      "false", Tk_Offset(struct Togl, DepthFlag), 0, NULL},
  325.  
  326.     {TK_CONFIG_INT, "-depthsize", "depthsize", "DepthSize",
  327.      "1", Tk_Offset(struct Togl, DepthSize), 0, NULL},
  328.  
  329.     {TK_CONFIG_BOOLEAN, "-accum", "accum", "Accum",
  330.      "false", Tk_Offset(struct Togl, AccumFlag), 0, NULL},
  331.  
  332.     {TK_CONFIG_INT, "-accumredsize", "accumredsize", "AccumRedSize",
  333.      "1", Tk_Offset(struct Togl, AccumRed), 0, NULL},
  334.  
  335.     {TK_CONFIG_INT, "-accumgreensize", "accumgreensize", "AccumGreenSize",
  336.      "1", Tk_Offset(struct Togl, AccumGreen), 0, NULL},
  337.  
  338.     {TK_CONFIG_INT, "-accumbluesize", "accumbluesize", "AccumBlueSize",
  339.      "1", Tk_Offset(struct Togl, AccumBlue), 0, NULL},
  340.  
  341.     {TK_CONFIG_INT, "-accumalphasize", "accumalphasize", "AccumAlphaSize",
  342.      "1", Tk_Offset(struct Togl, AccumAlpha), 0, NULL},
  343.  
  344.     {TK_CONFIG_BOOLEAN, "-alpha", "alpha", "Alpha",
  345.      "false", Tk_Offset(struct Togl, AlphaFlag), 0, NULL},
  346.  
  347.     {TK_CONFIG_INT, "-alphasize", "alphasize", "AlphaSize",
  348.      "1", Tk_Offset(struct Togl, AlphaSize), 0, NULL},
  349.  
  350.     {TK_CONFIG_BOOLEAN, "-stencil", "stencil", "Stencil",
  351.      "false", Tk_Offset(struct Togl, StencilFlag), 0, NULL},
  352.  
  353.     {TK_CONFIG_INT, "-stencilsize", "stencilsize", "StencilSize",
  354.      "1", Tk_Offset(struct Togl, StencilSize), 0, NULL},
  355.  
  356.     {TK_CONFIG_INT, "-auxbuffers", "auxbuffers", "AuxBuffers",
  357.      "0", Tk_Offset(struct Togl, AuxNumber), 0, NULL},
  358.  
  359.     {TK_CONFIG_BOOLEAN, "-privatecmap", "privateCmap", "PrivateCmap",
  360.      "false", Tk_Offset(struct Togl, PrivateCmapFlag), 0, NULL},
  361.  
  362.     {TK_CONFIG_BOOLEAN, "-overlay", "overlay", "Overlay",
  363.      "false", Tk_Offset(struct Togl, OverlayFlag), 0, NULL},
  364.  
  365.     {TK_CONFIG_BOOLEAN, "-stereo", "stereo", "Stereo",
  366.      "false", Tk_Offset(struct Togl, StereoFlag), 0, NULL},
  367.  
  368. #ifndef NO_TK_CURSOR
  369.     { TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor",
  370.      "", Tk_Offset(struct Togl, Cursor), TK_CONFIG_NULL_OK },
  371. #endif
  372.  
  373.     {TK_CONFIG_INT, "-time", "time", "Time",
  374.      DEFAULT_TIME, Tk_Offset(struct Togl, Time), 0, NULL},
  375.  
  376.     {TK_CONFIG_STRING, "-sharelist", "sharelist", "ShareList",
  377.      NULL, Tk_Offset(struct Togl, ShareList), 0, NULL},
  378.  
  379.     {TK_CONFIG_STRING, "-sharecontext", "sharecontext", "ShareContext",
  380.      NULL, Tk_Offset(struct Togl, ShareContext), 0, NULL},
  381.  
  382.     {TK_CONFIG_STRING, "-ident", "ident", "Ident",
  383.      DEFAULT_IDENT, Tk_Offset(struct Togl, Ident), 0, NULL},
  384.  
  385.     {TK_CONFIG_BOOLEAN, "-indirect", "indirect", "Indirect",
  386.      "false", Tk_Offset(struct Togl, Indirect), 0, NULL},
  387.  
  388.     {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
  389.      (char *) NULL, 0, 0, NULL}
  390. };
  391.  
  392.  
  393. static Togl_Callback *CreateProc = NULL;
  394. static Togl_Callback *DisplayProc = NULL;
  395. static Togl_Callback *ReshapeProc = NULL;
  396. static Togl_Callback *DestroyProc = NULL;
  397. static Togl_Callback *OverlayDisplayProc = NULL;
  398. static Togl_Callback *TimerProc = NULL;
  399. static ClientData DefaultClientData = NULL;
  400. static Tcl_HashTable CommandTable;
  401.  
  402. static struct Togl *ToglHead = NULL;  /* head of linked list */
  403.  
  404.  
  405. /*
  406.  * Add given togl widget to linked list.
  407.  */
  408. static void AddToList(struct Togl *t)
  409. {
  410.    t->Next = ToglHead;
  411.    ToglHead = t;
  412. }
  413.  
  414. /*
  415.  * Remove given togl widget from linked list.
  416.  */
  417. static void RemoveFromList(struct Togl *t)
  418. {
  419.    struct Togl *prev = NULL;
  420.    struct Togl *pos = ToglHead;
  421.    while (pos) {
  422.       if (pos == t) {
  423.          if (prev) {
  424.             prev->Next = pos->Next;
  425.          }
  426.          else {
  427.             ToglHead = pos->Next;
  428.          }
  429.          return;
  430.       }
  431.       prev = pos;
  432.       pos = pos->Next;
  433.    }
  434. }
  435.  
  436. /*
  437.  * Return pointer to togl widget given a user identifier string.
  438.  */
  439. static struct Togl *FindTogl(const char *ident)
  440. {
  441.    struct Togl *t = ToglHead;
  442.    while (t) {
  443.       if (strcmp(t->Ident, ident) == 0)
  444.          return t;
  445.       t = t->Next;
  446.    }
  447.    return NULL;
  448. }
  449.  
  450.  
  451.  
  452.  
  453. #if defined(X11)
  454. /*
  455.  * Return an X colormap to use for OpenGL RGB-mode rendering.
  456.  * Input:  dpy - the X display
  457.  *         scrnum - the X screen number
  458.  *         visinfo - the XVisualInfo as returned by glXChooseVisual()
  459.  * Return:  an X Colormap or 0 if there's a _serious_ error.
  460.  */
  461. static Colormap
  462. get_rgb_colormap( Display *dpy, int scrnum, const XVisualInfo *visinfo )
  463. {
  464.    Atom hp_cr_maps;
  465.    Status status;
  466.    int numCmaps;
  467.    int i;
  468.    XStandardColormap *standardCmaps;
  469.    Window root = RootWindow(dpy,scrnum);
  470.    int using_mesa;
  471.  
  472.    /*
  473.     * First check if visinfo's visual matches the default/root visual.
  474.     */
  475.    if (visinfo->visual==DefaultVisual(dpy,scrnum)) {
  476.       /* use the default/root colormap */
  477.       Colormap cmap;
  478.       cmap = DefaultColormap( dpy, scrnum );
  479. #ifdef MESA_COLOR_HACK
  480.       (void) get_free_color_cells( dpy, scrnum, cmap);
  481. #endif
  482.       return cmap;
  483.    }
  484.  
  485.    /*
  486.     * Check if we're using Mesa.
  487.     */
  488.    if (strstr(glXQueryServerString( dpy, scrnum, GLX_VERSION ), "Mesa")) {
  489.       using_mesa = 1;
  490.    }
  491.    else {
  492.       using_mesa = 0;
  493.    }
  494.  
  495.    /*
  496.     * Next, if we're using Mesa and displaying on an HP with the "Color
  497.     * Recovery" feature and the visual is 8-bit TrueColor, search for a
  498.     * special colormap initialized for dithering.  Mesa will know how to
  499.     * dither using this colormap.
  500.     */
  501.    if (using_mesa) {
  502.       hp_cr_maps = XInternAtom( dpy, "_HP_RGB_SMOOTH_MAP_LIST", True );
  503.       if (hp_cr_maps
  504. #ifdef __cplusplus
  505.       && visinfo->visual->c_class==TrueColor
  506. #else
  507.       && visinfo->visual->class==TrueColor
  508. #endif
  509.       && visinfo->depth==8) {
  510.      status = XGetRGBColormaps( dpy, root, &standardCmaps,
  511.                     &numCmaps, hp_cr_maps );
  512.      if (status) {
  513.         for (i=0; i<numCmaps; i++) {
  514.            if (standardCmaps[i].visualid == visinfo->visual->visualid) {
  515.                   Colormap cmap = standardCmaps[i].colormap;
  516.                   XFree( standardCmaps );
  517.           return cmap;
  518.            }
  519.         }
  520.             XFree(standardCmaps);
  521.      }
  522.       }
  523.    }
  524.  
  525.    /*
  526.     * Next, try to find a standard X colormap.
  527.     */
  528. #ifndef SOLARIS_BUG
  529.    status = XmuLookupStandardColormap( dpy, visinfo->screen,
  530.                        visinfo->visualid, visinfo->depth,
  531.                        XA_RGB_DEFAULT_MAP,
  532.                        /* replace */ False, /* retain */ True);
  533.    if (status == 1) {
  534.       status = XGetRGBColormaps( dpy, root, &standardCmaps,
  535.                  &numCmaps, XA_RGB_DEFAULT_MAP);
  536.       if (status == 1) {
  537.          for (i = 0; i < numCmaps; i++) {
  538.         if (standardCmaps[i].visualid == visinfo->visualid) {
  539.                Colormap cmap = standardCmaps[i].colormap;
  540.            XFree(standardCmaps);
  541.            return cmap;
  542.         }
  543.      }
  544.          XFree(standardCmaps);
  545.       }
  546.    }
  547. #endif
  548.  
  549.    /*
  550.     * If we get here, give up and just allocate a new colormap.
  551.     */
  552.    return XCreateColormap( dpy, root, visinfo->visual, AllocNone );
  553. }
  554. #elif defined(WIN32)
  555.  
  556. /* Code to create RGB palette is taken from the GENGL sample program
  557.    of Win32 SDK */
  558.  
  559. static unsigned char threeto8[8] = {
  560.     0, 0111>>1, 0222>>1, 0333>>1, 0444>>1, 0555>>1, 0666>>1, 0377
  561. };
  562.  
  563. static unsigned char twoto8[4] = {
  564.     0, 0x55, 0xaa, 0xff
  565. };
  566.  
  567. static unsigned char oneto8[2] = {
  568.     0, 255
  569. };
  570.  
  571. static int defaultOverride[13] = {
  572.     0, 3, 24, 27, 64, 67, 88, 173, 181, 236, 247, 164, 91
  573. };
  574.  
  575. static PALETTEENTRY defaultPalEntry[20] = {
  576.     { 0,   0,   0,    0 },
  577.     { 0x80,0,   0,    0 },
  578.     { 0,   0x80,0,    0 },
  579.     { 0x80,0x80,0,    0 },
  580.     { 0,   0,   0x80, 0 },
  581.     { 0x80,0,   0x80, 0 },
  582.     { 0,   0x80,0x80, 0 },
  583.     { 0xC0,0xC0,0xC0, 0 },
  584.  
  585.     { 192, 220, 192,  0 },
  586.     { 166, 202, 240,  0 },
  587.     { 255, 251, 240,  0 },
  588.     { 160, 160, 164,  0 },
  589.  
  590.     { 0x80,0x80,0x80, 0 },
  591.     { 0xFF,0,   0,    0 },
  592.     { 0,   0xFF,0,    0 },
  593.     { 0xFF,0xFF,0,    0 },
  594.     { 0,   0,   0xFF, 0 },
  595.     { 0xFF,0,   0xFF, 0 },
  596.     { 0,   0xFF,0xFF, 0 },
  597.     { 0xFF,0xFF,0xFF, 0 }
  598. };
  599.  
  600. static unsigned char
  601. ComponentFromIndex(int i, UINT nbits, UINT shift)
  602. {
  603.     unsigned char val;
  604.  
  605.     val = (unsigned char) (i >> shift);
  606.     switch (nbits) {
  607.  
  608.     case 1:
  609.         val &= 0x1;
  610.         return oneto8[val];
  611.  
  612.     case 2:
  613.         val &= 0x3;
  614.         return twoto8[val];
  615.  
  616.     case 3:
  617.         val &= 0x7;
  618.         return threeto8[val];
  619.  
  620.     default:
  621.         return 0;
  622.     }
  623. }
  624.  
  625. static Colormap Win32CreateRgbColormap(PIXELFORMATDESCRIPTOR pfd)
  626. {
  627.     TkWinColormap *cmap = (TkWinColormap *) ckalloc(sizeof(TkWinColormap));
  628.     LOGPALETTE *pPal;
  629.     int n, i;
  630.  
  631.     n = 1 << pfd.cColorBits;
  632.     pPal = (PLOGPALETTE)LocalAlloc(LMEM_FIXED, sizeof(LOGPALETTE) +
  633.             n * sizeof(PALETTEENTRY));
  634.     pPal->palVersion = 0x300;
  635.     pPal->palNumEntries = n;
  636.     for (i=0; i<n; i++) {
  637.         pPal->palPalEntry[i].peRed =
  638.                 ComponentFromIndex(i, pfd.cRedBits, pfd.cRedShift);
  639.         pPal->palPalEntry[i].peGreen =
  640.                 ComponentFromIndex(i, pfd.cGreenBits, pfd.cGreenShift);
  641.         pPal->palPalEntry[i].peBlue =
  642.                 ComponentFromIndex(i, pfd.cBlueBits, pfd.cBlueShift);
  643.         pPal->palPalEntry[i].peFlags = 0;
  644.     }
  645.  
  646.     /* fix up the palette to include the default GDI palette */
  647.     if ((pfd.cColorBits == 8)                           &&
  648.         (pfd.cRedBits   == 3) && (pfd.cRedShift   == 0) &&
  649.         (pfd.cGreenBits == 3) && (pfd.cGreenShift == 3) &&
  650.         (pfd.cBlueBits  == 2) && (pfd.cBlueShift  == 6)
  651.        ) {
  652.         for (i = 1 ; i <= 12 ; i++)
  653.             pPal->palPalEntry[defaultOverride[i]] = defaultPalEntry[i];
  654.     }
  655.  
  656.     cmap->palette = CreatePalette(pPal);
  657.     LocalFree(pPal);
  658.     cmap->size = n;
  659.     cmap->stale = 0;
  660.  
  661.     /* Since this is a private colormap of a fix size, we do not need
  662.        a valid hash table, but a dummy one */
  663.  
  664.     Tcl_InitHashTable(&cmap->refCounts, TCL_ONE_WORD_KEYS);
  665.     return (Colormap)cmap;
  666. }
  667.  
  668. static Colormap Win32CreateCiColormap(struct Togl *togl)
  669. {
  670.     /* Create a colormap with size of togl->CiColormapSize and set all
  671.        entries to black */
  672.  
  673.     LOGPALETTE logPalette;
  674.     TkWinColormap *cmap = (TkWinColormap *) ckalloc(sizeof(TkWinColormap));
  675.  
  676.     logPalette.palVersion = 0x300;
  677.     logPalette.palNumEntries = 1;
  678.     logPalette.palPalEntry[0].peRed = 0;
  679.     logPalette.palPalEntry[0].peGreen = 0;
  680.     logPalette.palPalEntry[0].peBlue = 0;
  681.     logPalette.palPalEntry[0].peFlags = 0;
  682.  
  683.     cmap->palette = CreatePalette(&logPalette);
  684.     cmap->size = togl->CiColormapSize;
  685.     ResizePalette(cmap->palette, cmap->size);  /* sets new entries to black */
  686.     cmap->stale = 0;
  687.  
  688.     /* Since this is a private colormap of a fix size, we do not need
  689.        a valid hash table, but a dummy one */
  690.  
  691.     Tcl_InitHashTable(&cmap->refCounts, TCL_ONE_WORD_KEYS);
  692.     return (Colormap)cmap;
  693. }
  694. #elif defined(__EMX__)
  695. /* OS/2 paletted mode not supported */
  696. #endif /*X11*/
  697.  
  698.  
  699.  
  700. /*
  701.  * Togl_Init
  702.  *
  703.  *   Called upon system startup to create Togl command.
  704.  */
  705. int Togl_Init(Tcl_Interp *interp)
  706. {
  707.    /* The Tcl_PkgProvide() function isn't available in Tcl 7.4 or earlier */
  708. #if (TCL_MAJOR_VERSION * 100 + TCL_MINOR_VERSION) > 704
  709.    /* The following allows Togl to be loaded dynamically into a running
  710.     * tclsh, if togl is made into a shared lib.  Contributed by Kerel
  711.     * Zuiderveld (karel.zuiderveld@cv.ruu.nl)
  712.     */
  713.    if (Tcl_PkgProvide(interp, "Togl", TOGL_VERSION) != TCL_OK) {
  714.       return TCL_ERROR;
  715.    }
  716. #endif
  717.  
  718.    Tcl_CreateCommand(interp, "togl", Togl_Cmd,
  719.                      (ClientData) Tk_MainWindow(interp), NULL);
  720.    Tcl_InitHashTable(&CommandTable, TCL_STRING_KEYS);
  721.  
  722.    return TCL_OK;
  723. }
  724.  
  725.  
  726. /*
  727.  * Register a C function to be called when an Togl widget is realized.
  728.  */
  729. void Togl_CreateFunc( Togl_Callback *proc )
  730. {
  731.    CreateProc = proc;
  732. }
  733.  
  734.  
  735. /*
  736.  * Register a C function to be called when an Togl widget must be redrawn.
  737.  */
  738. void Togl_DisplayFunc( Togl_Callback *proc )
  739. {
  740.    DisplayProc = proc;
  741. }
  742.  
  743.  
  744. /*
  745.  * Register a C function to be called when an Togl widget is resized.
  746.  */
  747. void Togl_ReshapeFunc( Togl_Callback *proc )
  748. {
  749.    ReshapeProc = proc;
  750. }
  751.  
  752.  
  753. /*
  754.  * Register a C function to be called when an Togl widget is destroyed.
  755.  */
  756. void Togl_DestroyFunc( Togl_Callback *proc )
  757. {
  758.    DestroyProc = proc;
  759. }
  760.  
  761.  
  762. /*
  763.  * Register a C function to be called from TimerEventHandler.
  764.  */
  765. void Togl_TimerFunc( Togl_Callback *proc )
  766. {
  767.    TimerProc = proc;
  768. }
  769.  
  770.  
  771. /*
  772.  * Reset default callback pointers to NULL.
  773.  */
  774. void Togl_ResetDefaultCallbacks( void )
  775. {
  776.    CreateProc = NULL;
  777.    DisplayProc = NULL;
  778.    ReshapeProc = NULL;
  779.    DestroyProc = NULL;
  780.    OverlayDisplayProc = NULL;
  781.    TimerProc = NULL;
  782.    DefaultClientData = NULL;
  783. }
  784.  
  785.  
  786. /*
  787.  * Chnage the create callback for a specific Togl widget.
  788.  */
  789. void Togl_SetCreateFunc( struct Togl *togl, Togl_Callback *proc )
  790. {
  791.    togl->CreateProc = proc;
  792. }
  793.  
  794.  
  795. /*
  796.  * Change the display/redraw callback for a specific Togl widget.
  797.  */
  798. void Togl_SetDisplayFunc( struct Togl *togl, Togl_Callback *proc )
  799. {
  800.    togl->DisplayProc = proc;
  801. }
  802.  
  803.  
  804. /*
  805.  * Change the reshape callback for a specific Togl widget.
  806.  */
  807. void Togl_SetReshapeFunc( struct Togl *togl, Togl_Callback *proc )
  808. {
  809.    togl->ReshapeProc = proc;
  810. }
  811.  
  812.  
  813. /*
  814.  * Change the destroy callback for a specific Togl widget.
  815.  */
  816. void Togl_SetDestroyFunc( struct Togl *togl, Togl_Callback *proc )
  817. {
  818.    togl->DestroyProc = proc;
  819. }
  820.  
  821.  
  822. /*
  823.  * Togl_Timer
  824.  *
  825.  * Gets called from Tk_CreateTimerHandler.
  826.  */
  827. static void Togl_Timer( ClientData clientData )
  828. {
  829.    struct Togl *togl = (struct Togl *) clientData;
  830.    togl->TimerProc(togl);
  831. #if (TK_MAJOR_VERSION * 100 + TK_MINOR_VERSION) >= 401
  832.    togl->timerHandler =
  833.        Tcl_CreateTimerHandler( togl->Time, Togl_Timer, (ClientData)togl );
  834. #else
  835.    togl->timerHandler =
  836.        Tk_CreateTimerHandler( togl->Time, Togl_Timer, (ClientData)togl );
  837. #endif
  838. }
  839.  
  840.  
  841. /*
  842.  * Togl_CreateCommand
  843.  *
  844.  *   Declares a new C sub-command of Togl callable from Tcl.
  845.  *   Every time the sub-command is called from Tcl, the
  846.  *   C routine will be called with all the arguments from Tcl.
  847.  */
  848. void Togl_CreateCommand( char *cmd_name, Togl_CmdProc *cmd_proc)
  849. {
  850.    int new_item;
  851.    Tcl_HashEntry *entry;
  852.    entry = Tcl_CreateHashEntry(&CommandTable, cmd_name, &new_item);
  853.    Tcl_SetHashValue(entry, cmd_proc);
  854. }
  855.  
  856.  
  857. /*
  858.  * Togl_MakeCurrent
  859.  *
  860.  *   Bind the OpenGL rendering context to the specified
  861.  *   Togl widget.
  862.  */
  863. void Togl_MakeCurrent( const struct Togl *togl )
  864. {
  865. #if defined(WIN32)
  866.    int res = wglMakeCurrent(togl->tglGLHdc, togl->tglGLHglrc);
  867.    assert(res == TRUE);
  868. #elif defined(__EMX__)
  869.    int res = pglMakeCurrent(togl->tglGLHab, togl->tglGLHgc, togl->tglGLHwnd);
  870.    assert(res == TRUE);
  871. #elif defined(X11)
  872.    glXMakeCurrent( Tk_Display(togl->TkWin),
  873.                    Tk_WindowId(togl->TkWin),
  874.                    togl->GlCtx );
  875. #if defined(__sgi) && defined(STEREO)
  876.    stereoMakeCurrent( Tk_Display(togl->TkWin),
  877.                       Tk_WindowId(togl->TkWin),
  878.                       togl->GlCtx );
  879. #endif /*__sgi STEREO */
  880. #endif /* WIN32 */
  881. }
  882.  
  883.  
  884. /*
  885.  * Called when the widget's contents must be redrawn.  Basically, we
  886.  * just call the user's render callback function.
  887.  *
  888.  * Note that the parameter type is ClientData so this function can be
  889.  * passed to Tk_DoWhenIdle().
  890.  */
  891. static void Togl_Render( ClientData clientData )
  892. {
  893.    struct Togl *togl = (struct Togl *)clientData;
  894.  
  895.    if (togl->DisplayProc) {
  896.       Togl_MakeCurrent(togl);
  897.       togl->DisplayProc(togl);
  898.    }
  899.    togl->UpdatePending = GL_FALSE;
  900. }
  901.  
  902.  
  903. static void RenderOverlay( ClientData clientData )
  904. {
  905.    struct Togl *togl = (struct Togl *)clientData;
  906.  
  907.    if (togl->OverlayFlag && togl->OverlayDisplayProc) {
  908. #if defined(WIN32)
  909.       int res = wglMakeCurrent(togl->tglGLHdc, togl->tglGLHglrc);
  910.       assert(res == TRUE);
  911. #elif defined(__EMX__)
  912.       int res = pglMakeCurrent(togl->tglGLHab, togl->tglGLHgc, togl->tglGLHwnd);
  913.       assert(res == TRUE);
  914. #elif defined(X11)
  915.       glXMakeCurrent( Tk_Display(togl->TkWin),
  916.               togl->OverlayWindow,
  917.               togl->OverlayCtx );
  918. #if defined(__sgi) && defined(STEREO)
  919.       stereoMakeCurrent( Tk_Display(togl->TkWin),
  920.                          togl->OverlayWindow,
  921.                          togl->OverlayCtx );    
  922. #endif /*__sgi STEREO */    
  923. #endif /* WIN32 */
  924.       togl->OverlayDisplayProc(togl);
  925.    }
  926.    togl->OverlayUpdatePending = GL_FALSE;
  927. }
  928.  
  929.  
  930. /*
  931.  * It's possible to change with this function or in a script some
  932.  * options like RGBA - ColorIndex ; Z-buffer and so on
  933.  */
  934. int Togl_Configure(Tcl_Interp *interp, struct Togl *togl,
  935.                    int argc, char *argv[], int flags)
  936. {
  937.    int oldRgbaFlag    = togl->RgbaFlag;
  938.    int oldRgbaRed     = togl->RgbaRed;
  939.    int oldRgbaGreen   = togl->RgbaGreen;
  940.    int oldRgbaBlue    = togl->RgbaBlue;
  941.    int oldDoubleFlag  = togl->DoubleFlag;
  942.    int oldDepthFlag   = togl->DepthFlag;
  943.    int oldDepthSize   = togl->DepthSize;
  944.    int oldAccumFlag   = togl->AccumFlag;
  945.    int oldAccumRed    = togl->AccumRed;
  946.    int oldAccumGreen  = togl->AccumGreen;
  947.    int oldAccumBlue   = togl->AccumBlue;
  948.    int oldAccumAlpha  = togl->AccumAlpha;
  949.    int oldAlphaFlag   = togl->AlphaFlag;
  950.    int oldAlphaSize   = togl->AlphaSize;
  951.    int oldStencilFlag = togl->StencilFlag;
  952.    int oldStencilSize = togl->StencilSize;
  953.    int oldAuxNumber   = togl->AuxNumber;
  954.  
  955.    if (Tk_ConfigureWidget(interp, togl->TkWin, configSpecs,
  956.                           argc, argv, (char *)togl, flags) == TCL_ERROR) {
  957.       return(TCL_ERROR);
  958.    }
  959.  
  960.    Tk_GeometryRequest(togl->TkWin, togl->Width, togl->Height);
  961.  
  962.    if (togl->RgbaFlag != oldRgbaFlag
  963.        || togl->RgbaRed != oldRgbaRed
  964.        || togl->RgbaGreen != oldRgbaGreen
  965.        || togl->RgbaBlue != oldRgbaBlue
  966.        || togl->DoubleFlag != oldDoubleFlag
  967.        || togl->DepthFlag != oldDepthFlag
  968.        || togl->DepthSize != oldDepthSize
  969.        || togl->AccumFlag != oldAccumFlag
  970.        || togl->AccumRed != oldAccumRed
  971.        || togl->AccumGreen != oldAccumGreen
  972.        || togl->AccumBlue != oldAccumBlue
  973.        || togl->AccumAlpha != oldAccumAlpha
  974.        || togl->AlphaFlag != oldAlphaFlag
  975.        || togl->AlphaSize != oldAlphaSize
  976.        || togl->StencilFlag != oldStencilFlag
  977.        || togl->StencilSize != oldStencilSize
  978.        || togl->AuxNumber != oldAuxNumber) {
  979. #ifdef MESA_COLOR_HACK
  980.       free_default_color_cells( Tk_Display(togl->TkWin),
  981.                                 Tk_Colormap(togl->TkWin) );
  982. #endif
  983.       /* Have to recreate the window and GLX context */
  984.       if (Togl_MakeWindowExist(togl)==TCL_ERROR) {
  985.          return TCL_ERROR;
  986.       }
  987.    }
  988.  
  989. #if defined(__sgi) && defined(STEREO)
  990.    stereoInit(togl,togl->StereoFlag);
  991. #endif
  992.  
  993.    return TCL_OK;
  994. }
  995.  
  996.  
  997. int Togl_Widget(ClientData clientData, Tcl_Interp *interp,
  998.            int argc, char *argv[])
  999. {
  1000.    struct Togl *togl = (struct Togl *)clientData;
  1001.    int result = TCL_OK;
  1002.    Tcl_HashEntry *entry;
  1003.    Tcl_HashSearch search;
  1004.    Togl_CmdProc *cmd_proc;
  1005.  
  1006.    if (argc < 2) {
  1007.       Tcl_AppendResult(interp, "wrong # args: should be \"",
  1008.                        argv[0], " ?options?\"", NULL);
  1009.       return TCL_ERROR;
  1010.    }
  1011.  
  1012.    Tk_Preserve((ClientData)togl);
  1013.  
  1014.    if (!strncmp(argv[1], "configure", MAX(1, strlen(argv[1])))) {
  1015.       if (argc == 2) {
  1016.          /* Return list of all configuration parameters */
  1017.          result = Tk_ConfigureInfo(interp, togl->TkWin, configSpecs,
  1018.                                    (char *)togl, (char *)NULL, 0);
  1019.       }
  1020.       else if (argc == 3) {
  1021.          if (strcmp(argv[2],"-extensions")==0) {
  1022.             /* Return a list of OpenGL extensions available */
  1023.             char *extensions;
  1024.             extensions = (char *) glGetString(GL_EXTENSIONS);
  1025.             Tcl_SetResult( interp, extensions, TCL_STATIC );
  1026.             result = TCL_OK;
  1027.          }
  1028.          else {
  1029.             /* Return a specific configuration parameter */
  1030.             result = Tk_ConfigureInfo(interp, togl->TkWin, configSpecs,
  1031.                                       (char *)togl, argv[2], 0);
  1032.          }
  1033.       }
  1034.       else {
  1035.          /* Execute a configuration change */
  1036.          result = Togl_Configure(interp, togl, argc-2, argv+2,
  1037.                                 TK_CONFIG_ARGV_ONLY);
  1038.       }
  1039.    }
  1040.    else if (!strncmp(argv[1], "render", MAX(1, strlen(argv[1])))) {
  1041.       /* force the widget to be redrawn */
  1042.       Togl_Render((ClientData) togl);
  1043.    }
  1044.    else if (!strncmp(argv[1], "swapbuffers", MAX(1, strlen(argv[1])))) {
  1045.       /* force the widget to be redrawn */
  1046.       Togl_SwapBuffers(togl);
  1047.    }
  1048.    else if (!strncmp(argv[1], "makecurrent", MAX(1, strlen(argv[1])))) {
  1049.       /* force the widget to be redrawn */
  1050.       Togl_MakeCurrent(togl);
  1051.    }
  1052.    else {
  1053.       /* Probably a user-defined function */
  1054.       entry = Tcl_FindHashEntry(&CommandTable, argv[1]);
  1055.       if (entry != NULL) {
  1056.          cmd_proc = (Togl_CmdProc *)Tcl_GetHashValue(entry);
  1057.          result = cmd_proc(togl, argc, argv);
  1058.       }
  1059.       else {
  1060.          Tcl_AppendResult(interp, "Togl: Unknown option: ", argv[1], "\n",
  1061.                           "Try: configure or render\n",
  1062.                           "or one of the user-defined commands:\n",
  1063.                           NULL);
  1064.          entry = Tcl_FirstHashEntry(&CommandTable, &search);
  1065.          while (entry) {
  1066.             Tcl_AppendResult(interp, "  ",
  1067.                              Tcl_GetHashKey(&CommandTable, entry),
  1068.                              "\n", NULL);
  1069.             entry = Tcl_NextHashEntry(&search);
  1070.          }
  1071.          result = TCL_ERROR;
  1072.       }
  1073.    }
  1074.  
  1075.    Tk_Release((ClientData)togl);
  1076.    return result;
  1077. }
  1078.  
  1079.  
  1080.  
  1081. /*
  1082.  * Togl_Cmd
  1083.  *
  1084.  *   Called when Togl is executed - creation of a Togl widget.
  1085.  *     * Creates a new window
  1086.  *     * Creates an 'Togl' data structure
  1087.  *     * Creates an event handler for this window
  1088.  *     * Creates a command that handles this object
  1089.  *     * Configures this Togl for the given arguments
  1090.  */
  1091. static int Togl_Cmd(ClientData clientData, Tcl_Interp *interp,
  1092.                     int argc, char **argv)
  1093. {
  1094.    char *name;
  1095.    Tk_Window main = (Tk_Window)clientData;
  1096.    Tk_Window tkwin;
  1097.    struct Togl *togl;
  1098.  
  1099.    if (argc <= 1) {
  1100.       TCL_ERR(interp, "wrong # args: should be \"pathName read filename\"");
  1101.    }
  1102.  
  1103.    /* Create the window. */
  1104.    name = argv[1];
  1105.    tkwin = Tk_CreateWindowFromPath(interp, main, name, (char *) NULL);
  1106.    if (tkwin == NULL) {
  1107.       return TCL_ERROR;
  1108.    }
  1109.  
  1110.    Tk_SetClass(tkwin, "Togl");
  1111.  
  1112.    /* Create Togl data structure */
  1113.    togl = (struct Togl *)malloc(sizeof(struct Togl));
  1114.    if (!togl) {
  1115.       return TCL_ERROR;
  1116.    }
  1117.  
  1118.    togl->Next = NULL;
  1119. #if defined(WIN32)
  1120.    togl->tglGLHdc = NULL;
  1121.    togl->tglGLHglrc = NULL;
  1122. #elif defined(__EMX__)
  1123.    togl->tglGLHgc = 0;
  1124.    togl->tglGLHwnd = 0;
  1125.    togl->tglGLHab = 0;
  1126. #elif defined(X11)
  1127.    togl->GlCtx = NULL;
  1128.    togl->OverlayCtx = NULL;
  1129. #endif /* WIN32 */
  1130.    togl->display = Tk_Display( tkwin );
  1131.    togl->TkWin = tkwin;
  1132.    togl->Interp = interp;
  1133. #ifndef NO_TK_CURSOR
  1134.    togl->Cursor = None;
  1135. #endif
  1136.    togl->Width = 0;
  1137.    togl->Height = 0;
  1138.    togl->Time = 0;
  1139.    togl->RgbaFlag = 1;
  1140.    togl->RgbaRed = 1;
  1141.    togl->RgbaGreen = 1;
  1142.    togl->RgbaBlue = 1;
  1143.    togl->DoubleFlag = 0;
  1144.    togl->DepthFlag = 0;
  1145.    togl->DepthSize = 1;
  1146.    togl->AccumFlag = 0;
  1147.    togl->AccumRed = 1;
  1148.    togl->AccumGreen = 1;
  1149.    togl->AccumBlue = 1;
  1150.    togl->AccumAlpha = 1;
  1151.    togl->AlphaFlag = 0;
  1152.    togl->AlphaSize = 1;
  1153.    togl->StencilFlag = 0;
  1154.    togl->StencilSize = 1;
  1155.    togl->OverlayFlag = 0;
  1156.    togl->StereoFlag = 0;
  1157.    togl->AuxNumber = 0;
  1158.    togl->Indirect = GL_FALSE;
  1159.    togl->UpdatePending = GL_FALSE;
  1160.    togl->OverlayUpdatePending = GL_FALSE;
  1161.    togl->CreateProc = CreateProc;
  1162.    togl->DisplayProc = DisplayProc;
  1163.    togl->ReshapeProc = ReshapeProc;
  1164.    togl->DestroyProc = DestroyProc;
  1165.    togl->TimerProc = TimerProc;
  1166.    togl->OverlayDisplayProc = OverlayDisplayProc;
  1167.    togl->ShareList = NULL;
  1168.    togl->ShareContext = NULL;
  1169.    togl->Ident = NULL;
  1170.    togl->Client_Data = DefaultClientData;
  1171.  
  1172.    /* for EPS Output */
  1173.    togl->EpsRedMap = togl->EpsGreenMap = togl->EpsBlueMap = NULL;
  1174.    togl->EpsMapSize = 0;
  1175.  
  1176.    /* Create command event handler */
  1177.    togl->widgetCmd = Tcl_CreateCommand(interp, Tk_PathName(tkwin),
  1178.                        Togl_Widget, (ClientData)togl,
  1179.                        (Tcl_CmdDeleteProc*) ToglCmdDeletedProc);
  1180.    Tk_CreateEventHandler(tkwin,
  1181.                          ExposureMask | StructureNotifyMask,
  1182.                          Togl_EventProc,
  1183.                          (ClientData)togl);
  1184.  
  1185.    /* Configure Togl widget */
  1186.    if (Togl_Configure(interp, togl, argc-2, argv+2, 0) == TCL_ERROR) {
  1187.       Tk_DestroyWindow(tkwin);
  1188.       goto error;
  1189.    }
  1190.  
  1191.    /*
  1192.     * If OpenGL window wasn't already created by Togl_Configure() we
  1193.     * create it now.  We can tell by checking if the GLX context has
  1194.     * been initialized.
  1195.     */
  1196. #if defined(WIN32)
  1197.    if (!togl->tglGLHdc) {
  1198. #elif defined(__EMX__)
  1199.    if (!togl->tglGLHgc) {
  1200. #elif defined(X11)
  1201.    if (!togl->GlCtx) {
  1202. #endif /* WIN32 */
  1203.       if (Togl_MakeWindowExist(togl) == TCL_ERROR) {
  1204.          goto error;
  1205.       }
  1206.    }
  1207.  
  1208.    /* If defined, call create callback */
  1209.    if (togl->CreateProc) {
  1210.       togl->CreateProc(togl);
  1211.    }
  1212.  
  1213.    /* If defined, call reshape proc */
  1214.    if (togl->ReshapeProc) {
  1215.       togl->ReshapeProc(togl);
  1216.    }
  1217.  
  1218.    /* If defined, setup timer */
  1219.    if (togl->TimerProc){
  1220.       Tk_CreateTimerHandler( togl->Time, Togl_Timer, (ClientData)togl );
  1221.    }
  1222.  
  1223.    Tcl_AppendResult(interp, Tk_PathName(tkwin), NULL);
  1224.  
  1225.    /* Add to linked list */
  1226.    AddToList(togl);
  1227.  
  1228.    return TCL_OK;
  1229.  
  1230. error:
  1231.    Tcl_DeleteCommand(interp, "togl");
  1232.    /*free(togl);   Don't free it, if we do a crash occurs later...*/
  1233.    return TCL_ERROR;
  1234. }
  1235.  
  1236.  
  1237.  
  1238. /*
  1239.  * Do all the setup for overlay planes
  1240.  * Return:   TCL_OK or TCL_ERROR
  1241.  */
  1242. static int SetupOverlay( struct Togl *togl )
  1243. {
  1244. #if defined(X11)
  1245.  
  1246. #ifdef GLX_TRANSPARENT_TYPE_EXT
  1247.    static int ovAttributeList[] = {
  1248.       GLX_BUFFER_SIZE, 2,
  1249.       GLX_LEVEL, 1,
  1250.       GLX_TRANSPARENT_TYPE_EXT, GLX_TRANSPARENT_INDEX_EXT,
  1251.       None
  1252.    };
  1253. #else
  1254.    static int ovAttributeList[] = {
  1255.       GLX_BUFFER_SIZE, 2,
  1256.       GLX_LEVEL, 1,
  1257.       None
  1258.    };
  1259. #endif
  1260.  
  1261.    Display *dpy;
  1262.    XVisualInfo *visinfo;
  1263.    TkWindow *winPtr = (TkWindow *) togl->TkWin;
  1264.  
  1265.    XSetWindowAttributes swa;
  1266.    Tcl_HashEntry *hPtr;
  1267.    int new_flag;
  1268.  
  1269.    dpy = Tk_Display(togl->TkWin);
  1270.  
  1271.    visinfo = glXChooseVisual( dpy, DefaultScreen(dpy), ovAttributeList );
  1272.    if (!visinfo){
  1273.       Tcl_AppendResult(togl->Interp,Tk_PathName(winPtr),
  1274.                        ": No suitable overlay index visual available",
  1275.                        (char *) NULL);
  1276.       togl->OverlayCtx = 0;
  1277.       togl->OverlayWindow = 0;
  1278.       togl->OverlayCmap = 0;
  1279.       return TCL_ERROR;
  1280.    }
  1281.  
  1282. #ifdef GLX_TRANSPARENT_INDEX_EXT
  1283.    {
  1284.       int fail = glXGetConfig(dpy, visinfo,GLX_TRANSPARENT_INDEX_VALUE_EXT,
  1285.                               &togl->OverlayTransparentPixel);
  1286.       if (fail)
  1287.          togl->OverlayTransparentPixel=0; /* maybe, maybe ... */
  1288.    }
  1289. #else
  1290.    togl->OverlayTransparentPixel=0; /* maybe, maybe ... */
  1291. #endif
  1292.  
  1293.    /*
  1294.    togl->OverlayCtx = glXCreateContext( dpy, visinfo, None, GL_TRUE );
  1295.    */
  1296.    /* NEW in Togl 1.5 beta 3 */
  1297.    /* share display lists with normal layer context */
  1298.    togl->OverlayCtx = glXCreateContext( dpy, visinfo,
  1299.                                         togl->GlCtx, !togl->Indirect );
  1300.  
  1301.    swa.colormap = XCreateColormap( dpy, RootWindow(dpy, visinfo->screen),
  1302.                                    visinfo->visual, AllocNone );
  1303.    togl->OverlayCmap = swa.colormap;
  1304.  
  1305.    swa.border_pixel = 0;
  1306.    swa.event_mask = ALL_EVENTS_MASK;
  1307.    togl->OverlayWindow = XCreateWindow( dpy, Tk_WindowId(togl->TkWin), 0, 0,
  1308.                                         togl->Width, togl->Height, 0,
  1309.                                         visinfo->depth, InputOutput,
  1310.                                         visinfo->visual,
  1311.                                         CWBorderPixel|CWColormap|CWEventMask,
  1312.                                         &swa );
  1313.  
  1314.    hPtr = Tcl_CreateHashEntry( &winPtr->dispPtr->winTable,
  1315.                                (char *) togl->OverlayWindow, &new_flag );
  1316.    Tcl_SetHashValue( hPtr, winPtr );
  1317.  
  1318. /*   XMapWindow( dpy, togl->OverlayWindow );*/
  1319.    togl->OverlayIsMapped = 0;
  1320.  
  1321.    /* Make sure window manager installs our colormap */
  1322.    XSetWMColormapWindows( dpy, togl->OverlayWindow, &togl->OverlayWindow, 1 );
  1323.  
  1324.    return TCL_OK;
  1325.  
  1326. #elif defined(WIN32)       /* not yet implemented on Windows*/
  1327.  
  1328.    return TCL_ERROR;
  1329.  
  1330. #elif defined(__EMX__)       /* not yet implemented on OS/2*/
  1331.  
  1332.    return TCL_ERROR;
  1333.  
  1334. #endif /* X11 */
  1335. }
  1336.  
  1337.  
  1338. #if defined(WIN32)
  1339. #define TOGL_CLASS_NAME "Togl Class"
  1340. static ToglClassInitialized = 0;
  1341.  
  1342. static LRESULT CALLBACK Win32WinProc( HWND hwnd, UINT message,
  1343.                                     WPARAM wParam, LPARAM lParam)
  1344. {
  1345.     LONG result;
  1346.     struct Togl *togl = (struct Togl*) GetWindowLong(hwnd, 0);
  1347.     TkWinColormap *cmap;
  1348.     HPALETTE OldPal;
  1349.     UINT i;
  1350.  
  1351.     switch( message ){
  1352.     case WM_WINDOWPOSCHANGED:
  1353.         /* Should be processed by DefWindowProc, otherwise a double buffered
  1354.         context is not properly resized when the corresponding window is resized.*/
  1355.         break;
  1356.     case WM_DESTROY:
  1357.         if (togl->tglGLHglrc) {
  1358.             wglDeleteContext(togl->tglGLHglrc);
  1359.         }
  1360.         if (togl->tglGLHdc) {
  1361.             ReleaseDC(hwnd, togl->tglGLHdc);
  1362.         }
  1363.         break;
  1364.     default:
  1365.         return TkWinChildProc(hwnd, message, wParam, lParam);
  1366.     }
  1367.     result = DefWindowProc(hwnd, message, wParam, lParam);
  1368.     Tcl_ServiceAll();
  1369.     return result;
  1370. }
  1371. #elif defined(__EMX__)
  1372. #define TOGL_CLASS_NAME "Togl Class"
  1373. /* Just some number for the window ID. */
  1374. #define TOGL_WNDID 0x69 
  1375.  
  1376. static MRESULT EXPENTRY OS2WndProc( HWND hwnd, ULONG msg,
  1377.                                     MPARAM mp1, MPARAM mp2)
  1378. {
  1379.     MRESULT result;
  1380.     struct Togl *togl = (struct Togl*) WinQueryWindowPtr(hwnd, QWL_USER);
  1381.     switch( msg ){
  1382.     case WM_WINDOWPOSCHANGED:
  1383.            /* Just doing what the windows version does. ... Maybe I don't need to */
  1384.         /* Should be processed by DefWindowProc, otherwise a double buffered
  1385.         context is not properly resized when the corresponding window is resized.*/
  1386.         break;
  1387.     case WM_DESTROY:
  1388.         if (togl->tglGLHgc) {
  1389.             pglDestroyContext(togl->tglGLHab, togl->tglGLHgc);
  1390.         }
  1391.         /*
  1392.         if (togl->tglGLHwnd) {
  1393.             WinDestroyWindow(togl->tglGLHwnd);
  1394.         }
  1395.         */
  1396.         break;
  1397.      default: 
  1398.         return TkOS2ChildProc(hwnd, msg, mp1, mp2);
  1399.     }
  1400.     result = WinDefWindowProc(hwnd, msg, mp1, mp2);
  1401.     Tcl_ServiceAll();
  1402.     return result;
  1403. }
  1404. #endif /* WIN32 */
  1405.  
  1406.  
  1407.  
  1408. /*
  1409.  * Togl_MakeWindowExist
  1410.  *
  1411.  *   Modified version of Tk_MakeWindowExist.
  1412.  *   Creates an OpenGL window for the Togl widget.
  1413.  */
  1414. static int Togl_MakeWindowExist(struct Togl *togl)
  1415. {
  1416.    XVisualInfo *visinfo = NULL;
  1417.    Display *dpy;
  1418.    int dummy;
  1419.    int attrib_list[1000];
  1420.    int attrib_count;
  1421.    TkWindow *winPtr = (TkWindow *) togl->TkWin;
  1422.    TkWindow *winPtr2;
  1423.    Window parent;
  1424.    Colormap cmap;
  1425.    XSetWindowAttributes swa;
  1426.    Tcl_HashEntry *hPtr;
  1427.    int new_flag;
  1428.    int scrnum;
  1429.    int attempt;
  1430.    int directCtx = GL_TRUE;
  1431.  
  1432. #if defined(X11)
  1433. #define MAX_ATTEMPTS 12
  1434.    static int ci_depths[MAX_ATTEMPTS] = {
  1435.       8, 4, 2, 1, 12, 16, 8, 4, 2, 1, 12, 16
  1436.    };
  1437.    static int dbl_flags[MAX_ATTEMPTS] = {
  1438.       0, 0, 0, 0,  0,  0, 1, 1, 1, 1,  1,  1
  1439.    };
  1440. #elif defined(WIN32)
  1441.    HWND hwnd, parentWin;
  1442.    int style, pixelformat;
  1443.    HANDLE hInstance;
  1444.    WNDCLASS ToglClass;
  1445.    PIXELFORMATDESCRIPTOR pfd;
  1446.    XVisualInfo VisInf;
  1447. #elif defined(__EMX__)
  1448. #define MAX_ATTEMPTS 12
  1449.    static int ci_depths[MAX_ATTEMPTS] = {
  1450.       8, 4, 2, 1, 12, 16, 8, 4, 2, 1, 12, 16
  1451.    };
  1452.    static int dbl_flags[MAX_ATTEMPTS] = {
  1453.       0, 0, 0, 0,  0,  0, 1, 1, 1, 1,  1,  1
  1454.    };
  1455.    HWND hwnd, parentWin;
  1456.    HAB hab;
  1457.    PVISUALCONFIG pvc;
  1458.    XVisualInfo VisInf;
  1459. #endif /* X11 */
  1460.  
  1461.    dpy = Tk_Display(togl->TkWin);
  1462.  
  1463.    if (winPtr->window != None) {
  1464.       XDestroyWindow(dpy, winPtr->window);
  1465.       winPtr->window = 0;
  1466.    }
  1467.  
  1468. #if defined(X11)
  1469.    /* Make sure OpenGL's GLX extension supported */
  1470.    if (!glXQueryExtension(dpy, &dummy, &dummy)) {
  1471.       TCL_ERR(togl->Interp, "Togl: X server has no OpenGL GLX extension");
  1472.    }
  1473.  
  1474.    if (togl->ShareContext && FindTogl(togl->ShareContext)) {
  1475.       /* share OpenGL context with existing Togl widget */
  1476.       struct Togl *shareWith = FindTogl(togl->ShareContext);
  1477.       assert(shareWith);
  1478.       assert(shareWith->GlCtx);
  1479.       togl->GlCtx = shareWith->GlCtx;
  1480.       togl->VisInfo = shareWith->VisInfo;
  1481.       visinfo = togl->VisInfo;
  1482.       printf("SHARE CTX\n");
  1483.    }
  1484.    else {
  1485.       /* It may take a few tries to get a visual */
  1486.       for (attempt=0; attempt<MAX_ATTEMPTS; attempt++) {
  1487.          attrib_count = 0;
  1488.          attrib_list[attrib_count++] = GLX_USE_GL;
  1489.          if (togl->RgbaFlag) {
  1490.             /* RGB[A] mode */
  1491.             attrib_list[attrib_count++] = GLX_RGBA;
  1492.             attrib_list[attrib_count++] = GLX_RED_SIZE;
  1493.             attrib_list[attrib_count++] = togl->RgbaRed;
  1494.             attrib_list[attrib_count++] = GLX_GREEN_SIZE;
  1495.             attrib_list[attrib_count++] = togl->RgbaGreen;
  1496.             attrib_list[attrib_count++] = GLX_BLUE_SIZE;
  1497.             attrib_list[attrib_count++] = togl->RgbaBlue;
  1498.             if (togl->AlphaFlag) {
  1499.                attrib_list[attrib_count++] = GLX_ALPHA_SIZE;
  1500.                attrib_list[attrib_count++] = togl->AlphaSize;
  1501.             }
  1502.  
  1503.             /* for EPS Output */
  1504.             if ( togl->EpsRedMap) free( ( char *)togl->EpsRedMap);
  1505.             if ( togl->EpsGreenMap) free( ( char *)togl->EpsGreenMap);
  1506.             if ( togl->EpsBlueMap) free( ( char *)togl->EpsBlueMap);
  1507.             togl->EpsRedMap = togl->EpsGreenMap = togl->EpsBlueMap = NULL;
  1508.             togl->EpsMapSize = 0;
  1509.          }
  1510.          else {
  1511.             /* Color index mode */
  1512.             int depth;
  1513.             attrib_list[attrib_count++] = GLX_BUFFER_SIZE;
  1514.             depth = ci_depths[attempt];
  1515.             attrib_list[attrib_count++] = depth;
  1516.          }
  1517.          if (togl->DepthFlag) {
  1518.             attrib_list[attrib_count++] = GLX_DEPTH_SIZE;
  1519.             attrib_list[attrib_count++] = togl->DepthSize;
  1520.          }
  1521.          if (togl->DoubleFlag || dbl_flags[attempt]) {
  1522.             attrib_list[attrib_count++] = GLX_DOUBLEBUFFER;
  1523.          }
  1524.          if (togl->StencilFlag) {
  1525.             attrib_list[attrib_count++] = GLX_STENCIL_SIZE;
  1526.             attrib_list[attrib_count++] = togl->StencilSize;
  1527.          }
  1528.          if (togl->AccumFlag) {
  1529.             attrib_list[attrib_count++] = GLX_ACCUM_RED_SIZE;
  1530.             attrib_list[attrib_count++] = togl->AccumRed;
  1531.             attrib_list[attrib_count++] = GLX_ACCUM_GREEN_SIZE;
  1532.             attrib_list[attrib_count++] = togl->AccumGreen;
  1533.             attrib_list[attrib_count++] = GLX_ACCUM_BLUE_SIZE;
  1534.             attrib_list[attrib_count++] = togl->AccumBlue;
  1535.             if (togl->AlphaFlag) {
  1536.                attrib_list[attrib_count++] = GLX_ACCUM_ALPHA_SIZE;
  1537.                attrib_list[attrib_count++] = togl->AccumAlpha;
  1538.             }
  1539.          }
  1540.          if (togl->AuxNumber != 0) {
  1541.             attrib_list[attrib_count++] = GLX_AUX_BUFFERS;
  1542.             attrib_list[attrib_count++] = togl->AuxNumber;
  1543.          }
  1544.          if (togl->Indirect) {
  1545.             directCtx = GL_FALSE;
  1546.          }
  1547.  
  1548.          /* stereo hack */
  1549.          /*
  1550.            if (togl->StereoFlag) {
  1551.            attrib_list[attrib_count++] = GLX_STEREO;
  1552.            }
  1553.          */
  1554.          attrib_list[attrib_count++] = None;
  1555.  
  1556.          visinfo = glXChooseVisual( dpy, DefaultScreen(dpy), attrib_list );
  1557.          if (visinfo) {
  1558.             /* found a GLX visual! */
  1559.             break;
  1560.          }
  1561.       }
  1562.  
  1563.       togl->VisInfo = visinfo;
  1564.  
  1565.       if (visinfo==NULL) {
  1566.          TCL_ERR(togl->Interp, "Togl: couldn't get visual");
  1567.       }
  1568.  
  1569.       /*
  1570.        * Create a new OpenGL rendering context.
  1571.        */
  1572.       if (togl->ShareList) {
  1573.          /* share display lists with existing togl widget */
  1574.          struct Togl *shareWith = FindTogl(togl->ShareList);
  1575.          GLXContext shareCtx;
  1576.          if (shareWith)
  1577.             shareCtx = shareWith->GlCtx;
  1578.          else
  1579.             shareCtx = None;
  1580.          togl->GlCtx = glXCreateContext(dpy, visinfo, shareCtx, directCtx);
  1581.       }
  1582.       else {
  1583.          /* don't share display lists */
  1584.          togl->GlCtx = glXCreateContext(dpy, visinfo, None, directCtx);
  1585.       }
  1586.  
  1587.       if (togl->GlCtx == NULL) {
  1588.          TCL_ERR(togl->Interp, "could not create rendering context");
  1589.       }
  1590.  
  1591.    }
  1592.  
  1593.  
  1594. #endif /* X11 */
  1595.  
  1596.    /* Find parent of window */
  1597.    /* Necessary for creation */
  1598.    if ((winPtr->parentPtr == NULL) || (winPtr->flags & TK_TOP_LEVEL)) {
  1599.       parent = XRootWindow(winPtr->display, winPtr->screenNum);
  1600.    }
  1601.    else {
  1602.       if (winPtr->parentPtr->window == None) {
  1603.          Tk_MakeWindowExist((Tk_Window) winPtr->parentPtr);
  1604.       }
  1605.       parent = winPtr->parentPtr->window;
  1606.    }
  1607.  
  1608. #if defined(WIN32)
  1609.    parentWin = Tk_GetHWND(parent);
  1610.    hInstance = Tk_GetHINSTANCE();
  1611.    if (ToglClassInitialized == 0) {
  1612.        ToglClassInitialized = 1;
  1613.        ToglClass.style = CS_HREDRAW | CS_VREDRAW;
  1614.        ToglClass.cbClsExtra = 0;
  1615.        ToglClass.cbWndExtra = 4;   /* to save struct Togl* */
  1616.        ToglClass.hInstance = hInstance;
  1617.        ToglClass.hbrBackground = NULL;
  1618.        ToglClass.lpszMenuName = NULL;
  1619.        ToglClass.lpszClassName = TOGL_CLASS_NAME;
  1620.        ToglClass.lpfnWndProc = Win32WinProc;
  1621.        ToglClass.hIcon = NULL;
  1622.        ToglClass.hCursor = NULL;
  1623.        if (!RegisterClass(&ToglClass)){
  1624.            TCL_ERR(togl->Interp, "unable register Togl window class");
  1625.        }
  1626.    }
  1627.  
  1628.    hwnd = CreateWindow(TOGL_CLASS_NAME, NULL, WS_CHILD | WS_CLIPCHILDREN
  1629.                        | WS_CLIPSIBLINGS, 0, 0, togl->Width, togl->Height,
  1630.                        parentWin, NULL, hInstance, NULL);
  1631.    SetWindowLong(hwnd, 0, (LONG) togl);
  1632.    SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0,
  1633.                   SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
  1634.  
  1635.    togl->tglGLHdc = GetDC(hwnd);
  1636.  
  1637.    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
  1638.    pfd.nVersion = 1;
  1639.    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
  1640.    if (togl->DoubleFlag) {
  1641.         pfd.dwFlags |= PFD_DOUBLEBUFFER;
  1642.    }
  1643.    /* The stereo flag is not supported in the current generic OpenGL
  1644.     * implementation, but may be supported by specific hardware devices.
  1645.     */
  1646.    if (togl->StereoFlag) {
  1647.         pfd.dwFlags |= PFD_STEREO;
  1648.    }
  1649.  
  1650.    pfd.cColorBits = togl->RgbaRed + togl->RgbaGreen + togl->RgbaBlue;
  1651.    pfd.iPixelType = togl->RgbaFlag ? PFD_TYPE_RGBA : PFD_TYPE_COLORINDEX;
  1652.    /* Alpha bitplanes are not supported in the current generic OpenGL
  1653.     * implementation, but may be supported by specific hardware devices.
  1654.     */
  1655.    pfd.cAlphaBits = togl->AlphaFlag ? togl->AlphaSize : 0;
  1656.    pfd.cAccumBits = togl->AccumFlag ? (togl->AccumRed + togl->AccumGreen +
  1657.                                        togl->AccumBlue +togl->AccumAlpha) : 0;
  1658.    pfd.cDepthBits = togl->DepthFlag ? togl->DepthSize : 0;
  1659.    pfd.cStencilBits = togl->StencilFlag ? togl->StencilSize : 0;
  1660.    /* Auxiliary buffers are not supported in the current generic OpenGL
  1661.     * implementation, but may be supported by specific hardware devices.
  1662.     */
  1663.    pfd.cAuxBuffers = togl->AuxNumber;
  1664.    pfd.iLayerType = PFD_MAIN_PLANE;
  1665.  
  1666.    if ( (pixelformat = ChoosePixelFormat(togl->tglGLHdc, &pfd)) == 0 ) {
  1667.         TCL_ERR(togl->Interp, "Togl: couldn't choose pixel format");
  1668.    }
  1669.    if (SetPixelFormat(togl->tglGLHdc, pixelformat, &pfd) == FALSE) {
  1670.         TCL_ERR(togl->Interp, "Togl: couldn't choose pixel format");
  1671.    }
  1672.  
  1673.    /* Get the actual pixel format */
  1674.    DescribePixelFormat(togl->tglGLHdc, pixelformat, sizeof(pfd), &pfd);
  1675.  
  1676.    /* Create an OpenGL rendering context */
  1677.    togl->tglGLHglrc = wglCreateContext(togl->tglGLHdc);
  1678.    if (!togl->tglGLHglrc) {
  1679.         TCL_ERR(togl->Interp, "could not create rendering context");
  1680.    }
  1681.  
  1682.    /* Just for portability, define the simplest visinfo */
  1683.    visinfo = &VisInf;
  1684.    visinfo->visual = DefaultVisual(dpy, DefaultScreen(dpy));
  1685.    visinfo->depth = visinfo->visual->bits_per_rgb;
  1686. #elif defined(__EMX__)
  1687.        parentWin = Tk_GetHWND(parent);
  1688.        hab = WinQueryAnchorBlock(parentWin);
  1689. /*  The PM window must be created with window client class CS_SIZEREDRAW
  1690.     and CS_MOVENOTIFY */
  1691.     /* Create our frame window. */
  1692.    if (!WinRegisterClass (hab, TOGL_CLASS_NAME, OS2WndProc,
  1693.            CS_SIZEREDRAW | CS_MOVENOTIFY, sizeof(PVOID))) {
  1694.            TCL_ERR(togl->Interp, "unable register Togl window class");
  1695.    }
  1696.    hwnd = WinCreateWindow (parentWin, TOGL_CLASS_NAME, 0, WS_VISIBLE | 
  1697.         WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 0, togl->Width, togl->Height,
  1698.         parentWin, HWND_TOP, TOGL_WNDID, NULL, NULL);
  1699.  
  1700.    WinSetWindowPtr(hwnd, QWL_USER, togl);
  1701.    togl->tglGLHab = hab;
  1702.    togl->tglGLHwnd = hwnd;
  1703.    if (togl->ShareContext && FindTogl(togl->ShareContext)) {
  1704.         TCL_ERR(togl->Interp, "context shareing not implemented in OS/2");
  1705.    }
  1706.    else {
  1707.       for (attempt=0; attempt<MAX_ATTEMPTS; attempt++) {
  1708.           attrib_count = 0;
  1709.         if (togl->RgbaFlag) {
  1710.             attrib_list[attrib_count++] = PGL_RGBA;
  1711.             attrib_list[attrib_count++] = PGL_RED_SIZE;
  1712.             attrib_list[attrib_count++] = togl->RgbaRed;
  1713.             attrib_list[attrib_count++] = PGL_GREEN_SIZE;
  1714.             attrib_list[attrib_count++] = togl->RgbaGreen;
  1715.                attrib_list[attrib_count++] = PGL_BLUE_SIZE;
  1716.             attrib_list[attrib_count++] = togl->RgbaBlue;
  1717.             if (togl->AlphaFlag) {
  1718.                 attrib_list[attrib_count++] = PGL_ALPHA_SIZE;
  1719.                 attrib_list[attrib_count++] = togl->AlphaSize;
  1720.             }
  1721.             /* NO EPS */
  1722.         } else {
  1723.             int depth;
  1724.             attrib_list[attrib_count++] = PGL_BUFFER_SIZE;
  1725.             depth = ci_depths[attempt];
  1726.             attrib_list[attrib_count++] = depth;
  1727.         } /* endif */
  1728.          if (togl->DepthFlag) {
  1729.             attrib_list[attrib_count++] = PGL_DEPTH_SIZE;
  1730.             attrib_list[attrib_count++] = togl->DepthSize;
  1731.          }
  1732.          if (togl->DoubleFlag || dbl_flags[attempt]) {
  1733.             attrib_list[attrib_count++] = PGL_DOUBLEBUFFER;
  1734.          }
  1735.          if (togl->StencilFlag) {
  1736.             attrib_list[attrib_count++] = PGL_STENCIL_SIZE;
  1737.             attrib_list[attrib_count++] = togl->StencilSize;
  1738.          }
  1739.          if (togl->AccumFlag) {
  1740.             attrib_list[attrib_count++] = PGL_ACCUM_RED_SIZE;
  1741.             attrib_list[attrib_count++] = togl->AccumRed;
  1742.             attrib_list[attrib_count++] = PGL_ACCUM_GREEN_SIZE;
  1743.             attrib_list[attrib_count++] = togl->AccumGreen;
  1744.             attrib_list[attrib_count++] = PGL_ACCUM_BLUE_SIZE;
  1745.             attrib_list[attrib_count++] = togl->AccumBlue;
  1746.             if (togl->AlphaFlag) {
  1747.                attrib_list[attrib_count++] = PGL_ACCUM_ALPHA_SIZE;
  1748.                attrib_list[attrib_count++] = togl->AccumAlpha;
  1749.             }
  1750.          }
  1751.          if (togl->AuxNumber != 0) {
  1752.             attrib_list[attrib_count++] = PGL_AUX_BUFFERS;
  1753.             attrib_list[attrib_count++] = togl->AuxNumber;
  1754.          }
  1755.          if (togl->Indirect) {
  1756.             directCtx = GL_FALSE;
  1757.          }
  1758.  
  1759.          /* stereo hack */
  1760.          /*
  1761.            if (togl->StereoFlag) {
  1762.            attrib_list[attrib_count++] = PGL_STEREO;
  1763.            }
  1764.          */
  1765.          attrib_list[attrib_count++] = None;
  1766.          pvc = pglChooseConfig(hab, attrib_list);
  1767.         if (pvc) break;
  1768.       }
  1769.       if (NULL==pvc) {
  1770.          TCL_ERR(togl->Interp, "Togl: couldn't get visual");
  1771.       }
  1772.       /* :TODO: Share List */
  1773.       /* Create an OpenGL rendering context */
  1774.       togl->tglGLHgc = pglCreateContext(hab,pvc,None,directCtx);
  1775.       if (!togl->tglGLHgc) {
  1776.             TCL_ERR(togl->Interp, "could not create rendering context");
  1777.       }
  1778.    }
  1779.    /* Windows does this, so I will too. */
  1780.    /* I probably should get rid of visinfo and replace it with pvc. */
  1781.    /* Just for portability, define the simplest visinfo */
  1782.    visinfo = &VisInf;
  1783.    visinfo->visual = DefaultVisual(dpy, DefaultScreen(dpy));
  1784.    visinfo->depth = visinfo->visual->bits_per_rgb;
  1785. #endif /*WIN32 */
  1786.  
  1787.  
  1788.    /*
  1789.     * find a colormap
  1790.     */
  1791.    scrnum = DefaultScreen(dpy);
  1792.    if (togl->RgbaFlag) {
  1793.       /* Colormap for RGB mode */
  1794. #if defined(X11)
  1795.       cmap = get_rgb_colormap( dpy, scrnum, visinfo );
  1796. #elif defined(WIN32)
  1797.       if (pfd.dwFlags & PFD_NEED_PALETTE) {
  1798.          cmap = Win32CreateRgbColormap(pfd);
  1799.       }
  1800.       else {
  1801.          cmap = DefaultColormap(dpy,scrnum);
  1802.       }
  1803.  
  1804.       /* for EPS Output */
  1805.       if ( togl->EpsRedMap) free( ( char *)togl->EpsRedMap);
  1806.       if ( togl->EpsGreenMap) free( ( char *)togl->EpsGreenMap);
  1807.       if ( togl->EpsBlueMap) free( ( char *)togl->EpsBlueMap);
  1808.       togl->EpsRedMap = togl->EpsGreenMap = togl->EpsBlueMap = NULL;
  1809.       togl->EpsMapSize = 0;
  1810. #elif defined(__EMX__)
  1811.     /* I've got no clue about this. */
  1812.     cmap = DefaultColormap(dpy,scrnum);
  1813. #endif /* X11 */
  1814.    }
  1815.    else {
  1816. #ifdef __EMX__
  1817.       TCL_ERR(togl->Interp, "Togl: Paletted mode not supporeted in OS/2");
  1818. #endif /* __EMX__ */
  1819.       /* Colormap for CI mode */
  1820. #ifdef WIN32
  1821.       togl->CiColormapSize = 1 << pfd.cColorBits;
  1822.       togl->CiColormapSize = togl->CiColormapSize < MAX_CI_COLORMAP_SIZE ?
  1823.                              togl->CiColormapSize : MAX_CI_COLORMAP_SIZE;
  1824.  
  1825. #endif /* WIN32 */
  1826.       if (togl->PrivateCmapFlag) {
  1827.          /* need read/write colormap so user can store own color entries */
  1828. #if defined(X11)
  1829.          cmap = XCreateColormap(dpy, RootWindow(dpy, visinfo->screen),
  1830.                                 visinfo->visual, AllocAll);
  1831. #elif defined(WIN32)
  1832.          cmap = Win32CreateCiColormap(togl);
  1833. #endif /* X11 */
  1834.       }
  1835.       else {
  1836.          if (visinfo->visual==DefaultVisual(dpy, scrnum)) {
  1837.             /* share default/root colormap */
  1838.             cmap = DefaultColormap(dpy,scrnum);
  1839.          }
  1840.          else {
  1841.             /* make a new read-only colormap */
  1842.             cmap = XCreateColormap(dpy, RootWindow(dpy, visinfo->screen),
  1843.                                    visinfo->visual, AllocNone);
  1844.          }
  1845.       }
  1846.    }
  1847.  
  1848.    /* Make sure Tk knows to switch to the new colormap when the cursor
  1849.     * is over this window when running in color index mode.
  1850.     */
  1851.    Tk_SetWindowVisual(togl->TkWin, visinfo->visual, visinfo->depth, cmap);
  1852. #ifdef WIN32
  1853.    /* Install the colormap */
  1854.    SelectPalette(togl->tglGLHdc, ((TkWinColormap *)cmap)->palette, TRUE);
  1855.    RealizePalette(togl->tglGLHdc);
  1856. #endif /* WIN32 */
  1857.  
  1858. #if defined(X11)
  1859.    swa.colormap = cmap;
  1860.    swa.border_pixel = 0;
  1861.    swa.event_mask = ALL_EVENTS_MASK;
  1862.    winPtr->window = XCreateWindow(dpy, parent,
  1863.                                   0, 0, togl->Width, togl->Height,
  1864.                                   0, visinfo->depth,
  1865.                                   InputOutput, visinfo->visual,
  1866.                                   CWBorderPixel | CWColormap | CWEventMask,
  1867.                                   &swa);
  1868.  
  1869.    /* Make sure window manager installs our colormap */
  1870.    XSetWMColormapWindows( dpy, winPtr->window, &winPtr->window, 1 );
  1871. #elif defined(WIN32)
  1872.    winPtr->window = Tk_AttachHWND((Tk_Window)winPtr, hwnd);
  1873. #elif defined(__EMX__)
  1874.    winPtr->window = Tk_AttachHWND((Tk_Window)winPtr, hwnd);
  1875. #endif /* X11 */
  1876.  
  1877.    /* This causes Tcl to crash under OS/2 for some strage reason.
  1878.       I suppose Tcl is only in beta */
  1879.    hPtr = Tcl_CreateHashEntry(&winPtr->dispPtr->winTable,
  1880.                               (char *) winPtr->window, &new_flag);
  1881.    Tcl_SetHashValue(hPtr, winPtr);
  1882.               
  1883.    winPtr->dirtyAtts = 0;
  1884.    winPtr->dirtyChanges = 0;
  1885. #ifdef TK_USE_INPUT_METHODS
  1886.    winPtr->inputContext = NULL;
  1887. #endif /* TK_USE_INPUT_METHODS */
  1888.  
  1889.    if (!(winPtr->flags & TK_TOP_LEVEL)) {
  1890.       /*
  1891.        * If any siblings higher up in the stacking order have already
  1892.        * been created then move this window to its rightful position
  1893.        * in the stacking order.
  1894.        *
  1895.        * NOTE: this code ignores any changes anyone might have made
  1896.        * to the sibling and stack_mode field of the window's attributes,
  1897.        * so it really isn't safe for these to be manipulated except
  1898.        * by calling Tk_RestackWindow.
  1899.        */
  1900.  
  1901.       for (winPtr2 = winPtr->nextPtr; winPtr2 != NULL;
  1902.            winPtr2 = winPtr2->nextPtr) {
  1903.          if ((winPtr2->window != None) && !(winPtr2->flags & TK_TOP_LEVEL)) {
  1904.             XWindowChanges changes;
  1905.             changes.sibling = winPtr2->window;
  1906.             changes.stack_mode = Below;
  1907.             XConfigureWindow(winPtr->display, winPtr->window,
  1908.                              CWSibling|CWStackMode, &changes);
  1909.             break;
  1910.          }
  1911.       }
  1912.  
  1913.       /*
  1914.        * If this window has a different colormap than its parent, add
  1915.        * the window to the WM_COLORMAP_WINDOWS property for its top-level.
  1916.        */
  1917.  
  1918.       if ((winPtr->parentPtr != NULL) &&
  1919.           (winPtr->atts.colormap != winPtr->parentPtr->atts.colormap)) {
  1920.          TkWmAddToColormapWindows(winPtr);
  1921.       }
  1922.    }
  1923.  
  1924.    if (togl->OverlayFlag) {
  1925.       if (SetupOverlay( togl )==TCL_ERROR) {
  1926.          fprintf(stderr,"Warning: couldn't setup overlay.\n");
  1927.          togl->OverlayFlag = 0;
  1928.       }
  1929.    }
  1930.  
  1931.    /*
  1932.     * Issue a ConfigureNotify event if there were deferred configuration
  1933.     * changes (but skip it if the window is being deleted;  the
  1934.     * ConfigureNotify event could cause problems if we're being called
  1935.     * from Tk_DestroyWindow under some conditions).
  1936.     */
  1937.    if ((winPtr->flags & TK_NEED_CONFIG_NOTIFY)
  1938.        && !(winPtr->flags & TK_ALREADY_DEAD)){
  1939.       XEvent event;
  1940.  
  1941.       winPtr->flags &= ~TK_NEED_CONFIG_NOTIFY;
  1942.  
  1943.       event.type = ConfigureNotify;
  1944.       event.xconfigure.serial = LastKnownRequestProcessed(winPtr->display);
  1945.       event.xconfigure.send_event = False;
  1946.       event.xconfigure.display = winPtr->display;
  1947.       event.xconfigure.event = winPtr->window;
  1948.       event.xconfigure.window = winPtr->window;
  1949.       event.xconfigure.x = winPtr->changes.x;
  1950.       event.xconfigure.y = winPtr->changes.y;
  1951.       event.xconfigure.width = winPtr->changes.width;
  1952.       event.xconfigure.height = winPtr->changes.height;
  1953.       event.xconfigure.border_width = winPtr->changes.border_width;
  1954.       if (winPtr->changes.stack_mode == Above) {
  1955.          event.xconfigure.above = winPtr->changes.sibling;
  1956.       }
  1957.       else {
  1958.          event.xconfigure.above = None;
  1959.       }
  1960.       event.xconfigure.override_redirect = winPtr->atts.override_redirect;
  1961.       Tk_HandleEvent(&event);
  1962.    }
  1963.  
  1964.    /* Request the X window to be displayed */
  1965.    XMapWindow(dpy, Tk_WindowId(togl->TkWin));
  1966.  
  1967.    /* Bind the context to the window and make it the current context. */
  1968.    Togl_MakeCurrent(togl);
  1969.  
  1970. #if defined(X11)
  1971.    /* Check for a single/double buffering snafu */
  1972.    {
  1973.       int dbl_flag;
  1974.       if (glXGetConfig( dpy, visinfo, GLX_DOUBLEBUFFER, &dbl_flag )) {
  1975.          if (togl->DoubleFlag==0 && dbl_flag) {
  1976.             /* We requested single buffering but had to accept a */
  1977.             /* double buffered visual.  Set the GL draw buffer to */
  1978.             /* be the front buffer to simulate single buffering. */
  1979.             glDrawBuffer( GL_FRONT );
  1980.          }
  1981.       }
  1982.    }
  1983. #elif defined(__EMX__)
  1984.    /* I probably want to do this */
  1985.    /* Check for a single/double buffering snafu */
  1986.    {
  1987.       if (togl->DoubleFlag==0 && pvc->doubleBuffer) {
  1988.          /* We requested single buffering but had to accept a */
  1989.          /* double buffered visual.  Set the GL draw buffer to */
  1990.          /* be the front buffer to simulate single buffering. */
  1991.          glDrawBuffer( GL_FRONT );
  1992.       }
  1993.    }
  1994. #endif /* X11 */
  1995.  
  1996.    /* for EPS Output */
  1997.    if ( !togl->RgbaFlag) {
  1998.       GLint index_bits;
  1999.       int index_size;
  2000. #if defined(X11)
  2001.       glGetIntegerv( GL_INDEX_BITS, &index_bits );
  2002.       index_size = 1 << index_bits;
  2003. #elif defined(__EMX__)
  2004.       /* Again, I have no clue about this */
  2005.       glGetIntegerv( GL_INDEX_BITS, &index_bits );
  2006.       index_size = 1 << index_bits;
  2007. #elif defined(WIN32)
  2008.       index_size = togl->CiColormapSize;
  2009. #endif /* X11 */
  2010.       if ( togl->EpsMapSize != index_size) {
  2011.          if ( togl->EpsRedMap) free( ( char *)togl->EpsRedMap);
  2012.          if ( togl->EpsGreenMap) free( ( char *)togl->EpsGreenMap);
  2013.          if ( togl->EpsBlueMap) free( ( char *)togl->EpsBlueMap);
  2014.          togl->EpsMapSize = index_size;
  2015.          togl->EpsRedMap = ( GLfloat *)calloc( index_size, sizeof( GLfloat));
  2016.          togl->EpsGreenMap = ( GLfloat *)calloc( index_size, sizeof( GLfloat));
  2017.          togl->EpsBlueMap = ( GLfloat *)calloc( index_size, sizeof( GLfloat));
  2018.       }
  2019.    }
  2020.  
  2021.    return TCL_OK;
  2022. }
  2023.  
  2024. /*
  2025.  * ToglCmdDeletedProc
  2026.  *
  2027.  *      This procedure is invoked when a widget command is deleted.  If
  2028.  *      the widget isn't already in the process of being destroyed,
  2029.  *      this command destroys it.
  2030.  *
  2031.  * Results:
  2032.  *      None.
  2033.  *
  2034.  * Side effects:
  2035.  *      The widget is destroyed.
  2036.  *
  2037.  *----------------------------------------------------------------------
  2038.  */ 
  2039. static void ToglCmdDeletedProc( ClientData clientData )
  2040. {
  2041.    struct Togl *togl = (struct Togl *)clientData;
  2042.    Tk_Window tkwin = togl->TkWin;
  2043.  
  2044.    /*
  2045.     * This procedure could be invoked either because the window was
  2046.     * destroyed and the command was then deleted (in which case tkwin
  2047.     * is NULL) or because the command was deleted, and then this procedure
  2048.     * destroys the widget.
  2049.     */
  2050.  
  2051.    /* NEW in togl 1.5 beta 3 */
  2052.    if (togl && tkwin) {
  2053.       Tk_DeleteEventHandler(tkwin,
  2054.                          ExposureMask | StructureNotifyMask,
  2055.                          Togl_EventProc,
  2056.                          (ClientData)togl);
  2057.    }
  2058.  
  2059.    /* NEW in togl 1.5 beta 3 */
  2060. #if defined(X11)
  2061.    if (togl->GlCtx) {
  2062.       /* XXX this might be bad if two or more Togl widgets share a context */
  2063.       glXDestroyContext( togl->display, togl->GlCtx );
  2064.       togl->GlCtx = NULL;
  2065.    }
  2066.    if (togl->OverlayCtx) {
  2067.       Tcl_HashEntry *entryPtr;
  2068.       TkWindow *winPtr = (TkWindow *) togl->TkWin;
  2069.       if (winPtr) {
  2070.          entryPtr = Tcl_FindHashEntry(&winPtr->dispPtr->winTable,
  2071.                                       (char *) togl->OverlayWindow );
  2072.          Tcl_DeleteHashEntry(entryPtr);
  2073.       }
  2074.       glXDestroyContext( togl->display, togl->OverlayCtx );
  2075.       togl->OverlayCtx = NULL;
  2076.    }
  2077. #endif
  2078.  
  2079.    if (tkwin != NULL) {
  2080.       togl->TkWin = NULL;
  2081.       Tk_DestroyWindow(tkwin);
  2082.    }
  2083. }
  2084.  
  2085.  
  2086. /*
  2087.  * Togl_Destroy
  2088.  *
  2089.  * Gets called when an Togl widget is destroyed.
  2090.  */
  2091. #if (TK_MAJOR_VERSION * 100 + TK_MINOR_VERSION) >= 401
  2092. static void Togl_Destroy( char *clientData )
  2093. #else
  2094. static void Togl_Destroy( ClientData clientData )
  2095. #endif
  2096. {
  2097.    struct Togl *togl = (struct Togl *)clientData;
  2098.  
  2099.    Tk_FreeOptions(configSpecs, (char *)togl, togl->display, 0);
  2100.  
  2101. #ifndef NO_TK_CURSOR
  2102.    if (togl->Cursor != None) {
  2103.       Tk_FreeCursor(togl->display, togl->Cursor);
  2104.    }
  2105. #endif
  2106.    if (togl->DestroyProc) {
  2107.       togl->DestroyProc(togl);
  2108.    }
  2109.  
  2110.    /* remove from linked list */
  2111.    RemoveFromList(togl);
  2112.  
  2113.    free(togl);
  2114. }
  2115.  
  2116.  
  2117.  
  2118. /*
  2119.  * This gets called to handle Togl window configuration events
  2120.  */
  2121. static void Togl_EventProc(ClientData clientData, XEvent *eventPtr)
  2122. {
  2123.    struct Togl *togl = (struct Togl *)clientData;
  2124.  
  2125.    switch (eventPtr->type) {
  2126.       case Expose:
  2127.          if (eventPtr->xexpose.count == 0) {
  2128.             if (!togl->UpdatePending &&
  2129.                 eventPtr->xexpose.window==Tk_WindowId(togl->TkWin)) {
  2130.                Togl_PostRedisplay(togl);
  2131.             }
  2132. #if defined(X11)
  2133.             if (!togl->OverlayUpdatePending && togl->OverlayFlag
  2134.                 && togl->OverlayIsMapped
  2135.                 && eventPtr->xexpose.window==togl->OverlayWindow){
  2136.                Togl_PostOverlayRedisplay(togl);
  2137.             }
  2138. #endif /*X11*/
  2139.          }
  2140.          break;
  2141.       case ConfigureNotify:
  2142.          if (togl->Width != Tk_Width(togl->TkWin) ||
  2143.              togl->Height != Tk_Height(togl->TkWin)) {
  2144.             togl->Width = Tk_Width(togl->TkWin);
  2145.             togl->Height = Tk_Height(togl->TkWin);
  2146.             XResizeWindow(Tk_Display(togl->TkWin), Tk_WindowId(togl->TkWin),
  2147.                           togl->Width, togl->Height);
  2148. #if defined(X11)
  2149.             if (togl->OverlayFlag) {
  2150.                XResizeWindow( Tk_Display(togl->TkWin), togl->OverlayWindow,
  2151.                               togl->Width, togl->Height );
  2152.                XRaiseWindow( Tk_Display(togl->TkWin), togl->OverlayWindow );
  2153.             }
  2154. #endif /*X11*/
  2155.             Togl_MakeCurrent(togl);
  2156.             if (togl->ReshapeProc) {
  2157.                togl->ReshapeProc(togl);
  2158.             }
  2159.             else {
  2160.                glViewport(0, 0, togl->Width, togl->Height);
  2161. #if defined(X11)
  2162.                if (togl->OverlayFlag) {
  2163.                   Togl_UseLayer( togl,TOGL_OVERLAY );
  2164.                   glViewport( 0, 0, togl->Width, togl->Height );
  2165.                   Togl_UseLayer( togl, TOGL_NORMAL );
  2166.                }
  2167. #endif /*X11*/
  2168.             }
  2169. #ifndef WIN32 /* causes double redisplay on Win32 platform */
  2170.             Togl_PostRedisplay(togl);
  2171. #endif /* WIN32 */
  2172.          }
  2173.          break;
  2174.       case MapNotify:
  2175.          break;
  2176.       case DestroyNotify:
  2177.      if (togl->TkWin != NULL) {
  2178.         togl->TkWin = NULL;
  2179. #if (TCL_MAJOR_VERSION * 100 + TCL_MINOR_VERSION) >= 800
  2180.             /* This function new in Tcl/Tk 8.0 */
  2181.             Tcl_DeleteCommandFromToken( togl->Interp, togl->widgetCmd );
  2182. #endif
  2183.      }
  2184.      if (togl->TimerProc != NULL) {
  2185. #if (TK_MAJOR_VERSION * 100 + TK_MINOR_VERSION) >= 401
  2186.         Tcl_DeleteTimerHandler(togl->timerHandler);
  2187. #else
  2188.         Tk_DeleteTimerHandler(togl->timerHandler);
  2189. #endif
  2190.         
  2191.      }
  2192.      if (togl->UpdatePending) {
  2193. #if (TCL_MAJOR_VERSION * 100 + TCL_MINOR_VERSION) >= 705
  2194.             Tcl_CancelIdleCall(Togl_Render, (ClientData) togl);
  2195. #else
  2196.             Tk_CancelIdleCall(Togl_Render, (ClientData) togl);
  2197. #endif
  2198.      }
  2199.  
  2200. #if (TK_MAJOR_VERSION * 100 + TK_MINOR_VERSION) >= 401
  2201.          Tcl_EventuallyFree( (ClientData) togl, Togl_Destroy );
  2202. #else
  2203.          Tk_EventuallyFree((ClientData)togl, Togl_Destroy);
  2204. #endif
  2205.  
  2206.          break;
  2207.       default:
  2208.          /*nothing*/
  2209.          ;
  2210.    }
  2211. }
  2212.  
  2213.  
  2214.  
  2215. void Togl_PostRedisplay( struct Togl *togl )
  2216. {
  2217.    if (!togl->UpdatePending) {
  2218.       Tk_DoWhenIdle( Togl_Render, (ClientData) togl );
  2219.       togl->UpdatePending = GL_TRUE;
  2220.    }
  2221. }
  2222.  
  2223.  
  2224.  
  2225. void Togl_SwapBuffers( const struct Togl *togl )
  2226. {
  2227.    if (togl->DoubleFlag) {
  2228. #if defined(WIN32)
  2229.       int res = SwapBuffers(togl->tglGLHdc);
  2230.       assert(res == TRUE);
  2231. #elif defined(__EMX__)
  2232.       pglSwapBuffers(togl->tglGLHab, togl->tglGLHwnd);
  2233.       
  2234. #elif defined(X11)
  2235.       glXSwapBuffers( Tk_Display(togl->TkWin), Tk_WindowId(togl->TkWin) );
  2236. #endif /* WIN32 */
  2237.    }
  2238.    else {
  2239.       glFlush();
  2240.    }
  2241. }
  2242.  
  2243.  
  2244.  
  2245. char *Togl_Ident( const struct Togl *togl )
  2246. {
  2247.    return togl->Ident;
  2248. }
  2249.  
  2250.  
  2251. int Togl_Width( const struct Togl *togl )
  2252. {
  2253.    return togl->Width;
  2254. }
  2255.  
  2256.  
  2257. int Togl_Height( const struct Togl *togl )
  2258. {
  2259.    return togl->Height;
  2260. }
  2261.  
  2262.  
  2263. Tcl_Interp *Togl_Interp( const struct Togl *togl )
  2264. {
  2265.    return togl->Interp;
  2266. }
  2267.  
  2268.  
  2269. Tk_Window Togl_TkWin( const struct Togl *togl )
  2270. {
  2271.    return togl->TkWin;
  2272. }
  2273.  
  2274.  
  2275. #if defined(X11)
  2276. /*
  2277.  * A replacement for XAllocColor.  This function should never
  2278.  * fail to allocate a color.  When XAllocColor fails, we return
  2279.  * the nearest matching color.  If we have to allocate many colors
  2280.  * this function isn't too efficient; the XQueryColors() could be
  2281.  * done just once.
  2282.  * Written by Michael Pichler, Brian Paul, Mark Kilgard
  2283.  * Input:  dpy - X display
  2284.  *         cmap - X colormap
  2285.  *         cmapSize - size of colormap
  2286.  * In/Out: color - the XColor struct
  2287.  * Output:  exact - 1=exact color match, 0=closest match
  2288.  */
  2289. static void
  2290. noFaultXAllocColor( Display *dpy, Colormap cmap, int cmapSize,
  2291.                     XColor *color, int *exact )
  2292. {
  2293.    XColor *ctable, subColor;
  2294.    int i, bestmatch;
  2295.    double mindist;       /* 3*2^16^2 exceeds long int precision.
  2296.                           */
  2297.  
  2298.    /* First try just using XAllocColor. */
  2299.    if (XAllocColor(dpy, cmap, color)) {
  2300.       *exact = 1;
  2301.       return;
  2302.    }
  2303.  
  2304.    /* Retrieve color table entries. */
  2305.    /* XXX alloca candidate. */
  2306.    ctable = (XColor *) malloc(cmapSize * sizeof(XColor));
  2307.    for (i = 0; i < cmapSize; i++) {
  2308.       ctable[i].pixel = i;
  2309.    }
  2310.    XQueryColors(dpy, cmap, ctable, cmapSize);
  2311.  
  2312.    /* Find best match. */
  2313.    bestmatch = -1;
  2314.    mindist = 0.0;
  2315.    for (i = 0; i < cmapSize; i++) {
  2316.       double dr = (double) color->red - (double) ctable[i].red;
  2317.       double dg = (double) color->green - (double) ctable[i].green;
  2318.       double db = (double) color->blue - (double) ctable[i].blue;
  2319.       double dist = dr * dr + dg * dg + db * db;
  2320.       if (bestmatch < 0 || dist < mindist) {
  2321.          bestmatch = i;
  2322.          mindist = dist;
  2323.       }
  2324.    }
  2325.  
  2326.    /* Return result. */
  2327.    subColor.red = ctable[bestmatch].red;
  2328.    subColor.green = ctable[bestmatch].green;
  2329.    subColor.blue = ctable[bestmatch].blue;
  2330.    free(ctable);
  2331.    /* Try to allocate the closest match color.  This should only
  2332.     * fail if the cell is read/write.  Otherwise, we're incrementing
  2333.     * the cell's reference count.
  2334.     */
  2335.    if (!XAllocColor(dpy, cmap, &subColor)) {
  2336.       /* do this to work around a problem reported by Frank Ortega */
  2337.       subColor.pixel = (unsigned long) bestmatch;
  2338.       subColor.red   = ctable[bestmatch].red;
  2339.       subColor.green = ctable[bestmatch].green;
  2340.       subColor.blue  = ctable[bestmatch].blue;
  2341.       subColor.flags = DoRed | DoGreen | DoBlue;
  2342.    }
  2343.    *color = subColor;
  2344. }
  2345.  
  2346. #elif defined(WIN32)
  2347.  
  2348. static UINT Win32AllocColor( const struct Togl *togl,
  2349.                              float red, float green, float blue )
  2350. {
  2351. /* Modified version of XAllocColor emulation of Tk.
  2352. *      - returns index, instead of color itself
  2353. *      - allocates logical palette entry even for non-palette devices
  2354. */
  2355.  
  2356.     TkWinColormap *cmap = (TkWinColormap *) Tk_Colormap(togl->TkWin);
  2357.     UINT index;
  2358.     COLORREF newColor, closeColor;
  2359.     PALETTEENTRY entry, closeEntry;
  2360.     int new, refCount;
  2361.     Tcl_HashEntry *entryPtr;
  2362.  
  2363.     entry.peRed =  red*255 + .5;
  2364.     entry.peGreen = green*255 + .5;
  2365.     entry.peBlue = blue*255 + .5;
  2366.     entry.peFlags = 0;
  2367.  
  2368.     /*
  2369.      * Find the nearest existing palette entry.
  2370.      */
  2371.  
  2372.     newColor = RGB(entry.peRed, entry.peGreen, entry.peBlue);
  2373.     index = GetNearestPaletteIndex(cmap->palette, newColor);
  2374.     GetPaletteEntries(cmap->palette, index, 1, &closeEntry);
  2375.     closeColor = RGB(closeEntry.peRed, closeEntry.peGreen,  closeEntry.peBlue);
  2376.  
  2377.      /*
  2378.      * If this is not a duplicate and colormap is not full, allocate a new entry.
  2379.      */
  2380.  
  2381.     if (newColor != closeColor) {
  2382.         if (cmap->size == togl->CiColormapSize) {
  2383.             entry = closeEntry;
  2384.         }
  2385.         else {
  2386.             cmap->size++;
  2387.             ResizePalette(cmap->palette, cmap->size);
  2388.             index = cmap->size -1;
  2389.             SetPaletteEntries(cmap->palette, index, 1, &entry);
  2390.             SelectPalette(togl->tglGLHdc, cmap->palette, TRUE);
  2391.             RealizePalette(togl->tglGLHdc);
  2392.         }
  2393.     }
  2394.     newColor = PALETTERGB(entry.peRed, entry.peGreen, entry.peBlue);
  2395.     entryPtr = Tcl_CreateHashEntry(&cmap->refCounts, (char *) newColor, &new);
  2396.     if (new) {
  2397.         refCount = 1;
  2398.     } else {
  2399.         refCount = ((int) Tcl_GetHashValue(entryPtr)) + 1;
  2400.     }
  2401.     Tcl_SetHashValue(entryPtr, (ClientData)refCount);
  2402.  
  2403.    /* for EPS output */
  2404.     togl->EpsRedMap[index] = entry.peRed / 255.0;
  2405.     togl->EpsGreenMap[index] = entry.peGreen / 255.0;
  2406.     togl->EpsBlueMap[index] = entry.peBlue / 255.0;
  2407.     return index;
  2408. }
  2409.  
  2410. static void Win32FreeColor( const struct Togl *togl, unsigned long index )
  2411. {
  2412.     TkWinColormap *cmap = (TkWinColormap *) Tk_Colormap(togl->TkWin);
  2413.     COLORREF cref;
  2414.     UINT count, refCount;
  2415.     PALETTEENTRY entry, *entries;
  2416.     Tcl_HashEntry *entryPtr;
  2417.  
  2418.     if (index >= cmap->size ) {
  2419.         panic("Tried to free a color that isn't allocated.");
  2420.     }
  2421.     GetPaletteEntries(cmap->palette, index, 1, &entry);
  2422.     cref = PALETTERGB(entry.peRed, entry.peGreen, entry.peBlue);
  2423.     entryPtr = Tcl_FindHashEntry(&cmap->refCounts, (char *) cref);
  2424.     if (!entryPtr) {
  2425.         panic("Tried to free a color that isn't allocated.");
  2426.     }
  2427.     refCount = (int) Tcl_GetHashValue(entryPtr) - 1;
  2428.     if (refCount == 0) {
  2429.         count = cmap->size - index;
  2430.         entries = (PALETTEENTRY *) ckalloc(sizeof(PALETTEENTRY)* count);
  2431.         GetPaletteEntries(cmap->palette, index+1, count, entries);
  2432.         SetPaletteEntries(cmap->palette, index, count, entries);
  2433.         SelectPalette(togl->tglGLHdc, cmap->palette, TRUE);
  2434.         RealizePalette(togl->tglGLHdc);
  2435.         ckfree((char *) entries);
  2436.         cmap->size--;
  2437.         Tcl_DeleteHashEntry(entryPtr);
  2438.     } else {
  2439.         Tcl_SetHashValue(entryPtr, (ClientData)refCount);
  2440.     }
  2441. }
  2442.  
  2443. static void Win32SetColor( const struct Togl *togl,
  2444.                     unsigned long index, float red, float green, float blue )
  2445. {
  2446.     TkWinColormap *cmap = (TkWinColormap *) Tk_Colormap(togl->TkWin);
  2447.     PALETTEENTRY entry;
  2448.  
  2449.     entry.peRed =  red*255 + .5;
  2450.     entry.peGreen = green*255 + .5;
  2451.     entry.peBlue = blue*255 + .5;
  2452.     entry.peFlags = 0;
  2453.     SetPaletteEntries(cmap->palette, index, 1, &entry);
  2454.     SelectPalette(togl->tglGLHdc, cmap->palette, TRUE);
  2455.     RealizePalette(togl->tglGLHdc);
  2456.  
  2457.     /* for EPS output */
  2458.     togl->EpsRedMap[index] = entry.peRed / 255.0;
  2459.     togl->EpsGreenMap[index] = entry.peGreen / 255.0;
  2460.     togl->EpsBlueMap[index] = entry.peBlue / 255.0;
  2461. }
  2462. #elif defined(__EMX__)
  2463. /*  paletted mode unsupported in OS/2 */
  2464. #endif /* X11 */
  2465.  
  2466.  
  2467. #ifndef __EMX__
  2468. /*  paletted mode unsupported in OS/2 */
  2469.  
  2470. unsigned long Togl_AllocColor( const struct Togl *togl,
  2471.                                float red, float green, float blue )
  2472. {
  2473.    XColor xcol;
  2474.    int exact;
  2475.  
  2476.    if (togl->RgbaFlag) {
  2477.       fprintf(stderr,"Error: Togl_AllocColor illegal in RGBA mode.\n");
  2478.       return 0;
  2479.    }
  2480.    /* TODO: maybe not... */
  2481.    if (togl->PrivateCmapFlag) {
  2482.       fprintf(stderr,"Error: Togl_FreeColor illegal with private colormap\n");
  2483.       return 0;
  2484.    }
  2485.  
  2486. #if defined(X11)
  2487.    xcol.red   = (short) (red   * 65535.0);
  2488.    xcol.green = (short) (green * 65535.0);
  2489.    xcol.blue  = (short) (blue  * 65535.0);
  2490.  
  2491.    noFaultXAllocColor( Tk_Display(togl->TkWin), Tk_Colormap(togl->TkWin),
  2492.                        Tk_Visual(togl->TkWin)->map_entries, &xcol, &exact );
  2493.  
  2494.  
  2495.    /* for EPS output */
  2496.    togl->EpsRedMap[ xcol.pixel] = xcol.red / 65535.0;
  2497.    togl->EpsGreenMap[ xcol.pixel] = xcol.green / 65535.0;
  2498.    togl->EpsBlueMap[ xcol.pixel] = xcol.blue / 65535.0;
  2499.  
  2500.    return xcol.pixel;
  2501. #elif defined(WIN32)
  2502.    return Win32AllocColor( togl, red, green, blue );
  2503. #endif /* X11 */
  2504. }
  2505.  
  2506.  
  2507.  
  2508. void Togl_FreeColor( const struct Togl *togl, unsigned long pixel )
  2509. {
  2510.    if (togl->RgbaFlag) {
  2511.       fprintf(stderr,"Error: Togl_AllocColor illegal in RGBA mode.\n");
  2512.       return;
  2513.    }
  2514.    /* TODO: maybe not... */
  2515.    if (togl->PrivateCmapFlag) {
  2516.       fprintf(stderr,"Error: Togl_FreeColor illegal with private colormap\n");
  2517.       return;
  2518.    }
  2519.  
  2520. #if defined(X11)
  2521.    XFreeColors( Tk_Display(togl->TkWin), Tk_Colormap(togl->TkWin),
  2522.                 &pixel, 1, 0 );
  2523. #elif defined(WIN32)
  2524.    Win32FreeColor(togl, pixel);
  2525. #endif /* X11 */
  2526. }
  2527.  
  2528.  
  2529.  
  2530. void Togl_SetColor( const struct Togl *togl,
  2531.                     unsigned long index, float red, float green, float blue )
  2532. {
  2533.    XColor xcol;
  2534.  
  2535.    if (togl->RgbaFlag) {
  2536.       fprintf(stderr,"Error: Togl_AllocColor illegal in RGBA mode.\n");
  2537.       return;
  2538.    }
  2539.    if (!togl->PrivateCmapFlag) {
  2540.       fprintf(stderr,"Error: Togl_SetColor requires a private colormap\n");
  2541.       return;
  2542.    }
  2543.  
  2544. #if defined(X11)
  2545.    xcol.pixel = index;
  2546.    xcol.red   = (short) (red   * 65535.0);
  2547.    xcol.green = (short) (green * 65535.0);
  2548.    xcol.blue  = (short) (blue  * 65535.0);
  2549.    xcol.flags = DoRed | DoGreen | DoBlue;
  2550.  
  2551.    XStoreColor( Tk_Display(togl->TkWin), Tk_Colormap(togl->TkWin), &xcol );
  2552.  
  2553.    /* for EPS output */
  2554.    togl->EpsRedMap[ xcol.pixel] = xcol.red / 65535.0;
  2555.    togl->EpsGreenMap[ xcol.pixel] = xcol.green / 65535.0;
  2556.    togl->EpsBlueMap[ xcol.pixel] = xcol.blue / 65535.0;
  2557.  
  2558. #elif defined(WIN32)
  2559.    Win32SetColor( togl, index, red, green, blue );
  2560. #endif /* X11 */
  2561. }
  2562. #endif /* __EMX__ */
  2563.  
  2564.  
  2565. #if defined(WIN32)
  2566. #include "tkFont.h"
  2567.  
  2568. /*
  2569.  * The following structure represents Windows' implementation of a font.
  2570.  */
  2571.  
  2572. typedef struct WinFont {
  2573.     TkFont font;        /* Stuff used by generic font package.  Must
  2574.                  * be first in structure. */
  2575.     HFONT hFont;        /* Windows information about font. */
  2576.     HWND hwnd;            /* Toplevel window of application that owns
  2577.                  * this font, used for getting HDC. */
  2578.     int widths[256];        /* Widths of first 256 chars in this font. */
  2579. } WinFont;
  2580. #endif /* WIN32 */
  2581.  
  2582. #ifndef __EMX__
  2583. /*  fonts unsupported in OS/2 */
  2584.  
  2585. #define MAX_FONTS 1000
  2586. static GLuint ListBase[MAX_FONTS];
  2587. static GLuint ListCount[MAX_FONTS];
  2588.  
  2589.  
  2590.  
  2591. /*
  2592.  * Load the named bitmap font as a sequence of bitmaps in a display list.
  2593.  * fontname may be one of the predefined fonts like TOGL_BITMAP_8_BY_13
  2594.  * or an X font name, or a Windows font name, etc.
  2595.  */
  2596. GLuint Togl_LoadBitmapFont( const struct Togl *togl, const char *fontname )
  2597. {
  2598.    static int FirstTime = 1;
  2599. #if defined(X11)
  2600.    XFontStruct *fontinfo;
  2601. #elif defined(WIN32)
  2602.    WinFont *winfont;
  2603.    HFONT oldFont;
  2604.    TEXTMETRIC tm;
  2605. #endif /* X11 */
  2606.    int first, last, count;
  2607.    GLuint fontbase;
  2608.    const char *name;
  2609.  
  2610.    /* Initialize the ListBase and ListCount arrays */
  2611.    if (FirstTime) {
  2612.       int i;
  2613.       for (i=0;i<MAX_FONTS;i++) {
  2614.          ListBase[i] = ListCount[i] = 0;
  2615.       }
  2616.       FirstTime = 0;
  2617.    }
  2618.  
  2619.    /*
  2620.     * This method of selecting X fonts according to a TOGL_ font name
  2621.     * is a kludge.  To be fixed when I find time...
  2622.     */
  2623.    if (fontname==TOGL_BITMAP_8_BY_13) {
  2624.       name = "8x13";
  2625.    }
  2626.    else if (fontname==TOGL_BITMAP_9_BY_15) {
  2627.       name = "9x15";
  2628.    }
  2629.    else if (fontname==TOGL_BITMAP_TIMES_ROMAN_10) {
  2630.       name = "-adobe-times-medium-r-normal--10-100-75-75-p-54-iso8859-1";
  2631.    }
  2632.    else if (fontname==TOGL_BITMAP_TIMES_ROMAN_24) {
  2633.       name = "-adobe-times-medium-r-normal--24-240-75-75-p-124-iso8859-1";
  2634.    }
  2635.    else if (fontname==TOGL_BITMAP_HELVETICA_10) {
  2636.       name = "-adobe-helvetica-medium-r-normal--10-100-75-75-p-57-iso8859-1";
  2637.    }
  2638.    else if (fontname==TOGL_BITMAP_HELVETICA_12) {
  2639.       name = "-adobe-helvetica-medium-r-normal--12-120-75-75-p-67-iso8859-1";
  2640.    }
  2641.    else if (fontname==TOGL_BITMAP_HELVETICA_18) {
  2642.       name = "-adobe-helvetica-medium-r-normal--18-180-75-75-p-98-iso8859-1";
  2643.    }
  2644.    else if (!fontname) {
  2645.       name = DEFAULT_FONTNAME;
  2646.    }
  2647.    else {
  2648.       name = (const char *) fontname;
  2649.    }
  2650.  
  2651.    assert( name );
  2652.  
  2653. #if defined(X11)
  2654.    fontinfo = XLoadQueryFont( Tk_Display(togl->TkWin), name );
  2655.    if (!fontinfo) {
  2656.       return 0;
  2657.    }
  2658.  
  2659.    first = fontinfo->min_char_or_byte2;
  2660.    last = fontinfo->max_char_or_byte2;
  2661. #elif defined(WIN32)
  2662.    winfont = (WinFont*) Tk_GetFont(togl->Interp, togl->TkWin, name);
  2663.    if (!winfont) {
  2664.       return 0;
  2665.    }
  2666.    oldFont = SelectObject(togl->tglGLHdc, winfont->hFont);
  2667.    GetTextMetrics(togl->tglGLHdc, &tm);
  2668.    first = tm.tmFirstChar;
  2669.    last = tm.tmLastChar;
  2670. #endif /* X11 */
  2671.    count = last-first+1;
  2672.  
  2673.    fontbase = glGenLists( (GLuint) (last+1) );
  2674.    if (fontbase==0) {
  2675. #ifdef WIN32
  2676.       SelectObject(togl->tglGLHdc, oldFont);
  2677.       Tk_FreeFont((Tk_Font) winfont);
  2678. #endif /* WIN32 */
  2679.       return 0;
  2680.    }
  2681. #if defined(WIN32)
  2682.    wglUseFontBitmaps(togl->tglGLHdc, first, count, (int) fontbase+first );
  2683.    SelectObject(togl->tglGLHdc, oldFont);
  2684.    Tk_FreeFont((Tk_Font) winfont);
  2685. #elif defined(X11)
  2686.    glXUseXFont( fontinfo->fid, first, count, (int) fontbase+first );
  2687. #endif
  2688.  
  2689.    /* Record the list base and number of display lists
  2690.     * for Togl_UnloadBitmapFont().
  2691.     */
  2692.    {
  2693.       int i;
  2694.       for (i=0;i<MAX_FONTS;i++) {
  2695.          if (ListBase[i]==0) {
  2696.             ListBase[i] = fontbase;
  2697.             ListCount[i] = last+1;
  2698.             break;
  2699.          }
  2700.       }
  2701.    }
  2702.  
  2703.    return fontbase;
  2704. }
  2705.  
  2706.  
  2707.  
  2708. /*
  2709.  * Release the display lists which were generated by Togl_LoadBitmapFont().
  2710.  */
  2711. void Togl_UnloadBitmapFont( const struct Togl *togl, GLuint fontbase )
  2712. {
  2713.    int i;
  2714.    (void) togl;
  2715.    for (i=0;i<MAX_FONTS;i++) {
  2716.       if (ListBase[i]==fontbase) {
  2717.          glDeleteLists( ListBase[i], ListCount[i] );
  2718.          ListBase[i] = ListCount[i] = 0;
  2719.          return;
  2720.       }
  2721.    }
  2722. }
  2723. #endif /* __EMX__ */
  2724.  
  2725.  
  2726. /*
  2727.  * Overlay functions
  2728.  */
  2729.  
  2730.  
  2731. void Togl_UseLayer( struct Togl *togl, int layer )
  2732. {
  2733.    if (togl->OverlayWindow) {
  2734.       if (layer==TOGL_OVERLAY) {
  2735. #if defined(WIN32)
  2736.          int res = wglMakeCurrent(togl->tglGLHdc, togl->tglGLOverlayHglrc);
  2737.          assert(res == TRUE);
  2738. #elif defined(__EMX__)
  2739.          /* Unsupported */
  2740.             assert(0);
  2741. #elif defined(X11)
  2742.      glXMakeCurrent( Tk_Display(togl->TkWin),
  2743.              togl->OverlayWindow,
  2744.              togl->OverlayCtx );
  2745. #if defined(__sgi) && defined(STEREO)
  2746.     stereoMakeCurrent( Tk_Display(togl->TkWin),
  2747.                togl->OverlayWindow,
  2748.                togl->OverlayCtx );
  2749. #endif /* __sgi STEREO */
  2750. #endif /*WIN32 */
  2751.       }
  2752.       else if (layer==TOGL_NORMAL) {
  2753. #if defined(WIN32)
  2754.     int res = wglMakeCurrent(togl->tglGLHdc, togl->tglGLHglrc);
  2755.     assert(res == TRUE);
  2756. #elif defined(__EMX__)
  2757.     int res = pglMakeCurrent(togl->tglGLHab, togl->tglGLHgc, togl->tglGLHwnd);
  2758.     assert(res == TRUE);
  2759. #elif defined(X11)
  2760.     glXMakeCurrent( Tk_Display(togl->TkWin),
  2761.             Tk_WindowId(togl->TkWin),
  2762.             togl->GlCtx );
  2763. #if defined(__sgi) && defined(STEREO)
  2764.     stereoMakeCurrent( Tk_Display(togl->TkWin),
  2765.             Tk_WindowId(togl->TkWin),
  2766.             togl->GlCtx );
  2767. #endif /* __sgi STEREO */
  2768. #endif /* WIN32 */
  2769.       }
  2770.       else {
  2771.          /* error */
  2772.       }
  2773.    }
  2774. }
  2775.  
  2776.  
  2777.  
  2778. #if defined(X11)  /* not yet implemented on Windows*/
  2779. void Togl_ShowOverlay( struct Togl *togl )
  2780. {
  2781.    if (togl->OverlayWindow) {
  2782.       XMapWindow( Tk_Display(togl->TkWin), togl->OverlayWindow );
  2783.       XInstallColormap(Tk_Display(togl->TkWin),togl->OverlayCmap);
  2784.       togl->OverlayIsMapped = 1;
  2785.    }
  2786. }
  2787. #endif /* X11 */
  2788.  
  2789.  
  2790.  
  2791. void Togl_HideOverlay( struct Togl *togl )
  2792. {
  2793.    if (togl->OverlayWindow && togl->OverlayIsMapped) {
  2794.       XUnmapWindow( Tk_Display(togl->TkWin), togl->OverlayWindow );
  2795.       togl->OverlayIsMapped=0;
  2796.    }
  2797. }
  2798.  
  2799.  
  2800.  
  2801. void Togl_PostOverlayRedisplay( struct Togl *togl )
  2802. {
  2803.    if (!togl->OverlayUpdatePending
  2804.        && togl->OverlayWindow && togl->OverlayDisplayProc) {
  2805.       Tk_DoWhenIdle( RenderOverlay, (ClientData) togl );
  2806.       togl->OverlayUpdatePending = 1;
  2807.    }
  2808. }
  2809.  
  2810.  
  2811. void Togl_OverlayDisplayFunc( Togl_Callback *proc )
  2812. {
  2813.    OverlayDisplayProc = proc;
  2814. }
  2815.  
  2816.  
  2817. int Togl_ExistsOverlay( const struct Togl *togl )
  2818. {
  2819.    return togl->OverlayFlag;
  2820. }
  2821.  
  2822.  
  2823. int Togl_GetOverlayTransparentValue( const struct Togl *togl )
  2824. {
  2825.    return togl->OverlayTransparentPixel;
  2826. }
  2827.  
  2828.  
  2829. int Togl_IsMappedOverlay( const struct Togl *togl )
  2830. {
  2831.    return togl->OverlayFlag && togl->OverlayIsMapped;
  2832. }
  2833.  
  2834.  
  2835. #if defined(X11) /* not yet implemented on Windows*/
  2836. unsigned long Togl_AllocColorOverlay( const struct Togl *togl,
  2837.                                       float red, float green, float blue )
  2838. {
  2839.    if (togl->OverlayFlag && togl->OverlayCmap) {
  2840.       XColor xcol;
  2841.       xcol.red   = (short) (red* 65535.0);
  2842.       xcol.green = (short) (green* 65535.0);
  2843.       xcol.blue  = (short) (blue* 65535.0);
  2844.       if (!XAllocColor(Tk_Display(togl->TkWin),togl->OverlayCmap,&xcol))
  2845.          return (unsigned long) -1;
  2846.       return xcol.pixel;
  2847.    }
  2848.    else {
  2849.       return (unsigned long) -1;
  2850.    }
  2851. }
  2852.  
  2853.  
  2854. void Togl_FreeColorOverlay( const struct Togl *togl, unsigned long pixel )
  2855. {
  2856.  
  2857.    if (togl->OverlayFlag && togl->OverlayCmap) {
  2858.       XFreeColors( Tk_Display(togl->TkWin), togl->OverlayCmap,
  2859.                    &pixel, 1, 0 );
  2860.    }
  2861. }
  2862. #endif /* X11 */
  2863.  
  2864.  
  2865.  
  2866. /*
  2867.  * User client data
  2868.  */
  2869.  
  2870. void Togl_ClientData( ClientData clientData )
  2871. {
  2872.    DefaultClientData = clientData;
  2873. }
  2874.  
  2875.  
  2876. ClientData Togl_GetClientData( const struct Togl *togl )
  2877. {
  2878.    return togl->Client_Data;
  2879. }
  2880.  
  2881.  
  2882. void Togl_SetClientData( struct Togl *togl, ClientData clientData )
  2883. {
  2884.    togl->Client_Data = clientData;
  2885. }
  2886.  
  2887.  
  2888.  
  2889. /*
  2890.  * X11-only functions
  2891.  * Contributed by Miguel A. De Riera Pasenau (miguel@DALILA.UPC.ES)
  2892.  */
  2893.  
  2894. Display* Togl_Display( const struct Togl *togl)
  2895. {
  2896.    return Tk_Display(togl->TkWin);
  2897. }
  2898.  
  2899. Screen* Togl_Screen( const struct Togl *togl)
  2900. {
  2901.    return Tk_Screen(togl->TkWin);
  2902. }
  2903.  
  2904. int Togl_ScreenNumber( const struct Togl *togl)
  2905. {
  2906.    return Tk_ScreenNumber(togl->TkWin);
  2907. }
  2908.  
  2909. Colormap Togl_Colormap( const struct Togl *togl)
  2910. {
  2911.    return Tk_Colormap(togl->TkWin);
  2912. }
  2913.  
  2914.  
  2915.  
  2916. #ifdef MESA_COLOR_HACK
  2917. /*
  2918.  * Let's know how many free colors do we have
  2919.  */
  2920. #if 0
  2921. static unsigned char rojo[] = { 4, 39, 74, 110, 145, 181, 216, 251},
  2922.                      verde[] = { 4, 39, 74, 110, 145, 181, 216, 251},
  2923.              azul[] = { 4, 39, 74, 110, 145, 181, 216, 251};
  2924.  
  2925. unsigned char rojo[] = { 4, 36, 72, 109, 145, 182, 218, 251},
  2926.               verde[] = { 4, 36, 72, 109, 145, 182, 218, 251},
  2927.               azul[] = { 4, 36, 72, 109, 145, 182, 218, 251};
  2928.               azul[] = { 0, 85, 170, 255};
  2929. #endif
  2930.  
  2931. #define RLEVELS     5
  2932. #define GLEVELS     9
  2933. #define BLEVELS     5
  2934.  
  2935. /* to free dithered_rgb_colormap pixels allocated by Mesa */
  2936. static unsigned long *ToglMesaUsedPixelCells = NULL;
  2937. static int ToglMesaUsedFreeCells = 0;
  2938.  
  2939. static int get_free_color_cells( Display *display, int screen,
  2940.                                  Colormap colormap)
  2941. {
  2942.    if ( !ToglMesaUsedPixelCells) {
  2943.       XColor xcol;
  2944.       int i;
  2945.       int colorsfailed, ncolors = XDisplayCells( display, screen);
  2946.  
  2947.       long r, g, b;
  2948.  
  2949.       ToglMesaUsedPixelCells = ( unsigned long *)calloc( ncolors, sizeof( unsigned long));
  2950.  
  2951.       /* Allocate X colors and initialize color_table[], red_table[], etc */
  2952.       /* de Mesa 2.1: xmesa1.c setup_dithered_(...) */
  2953.       i = colorsfailed = 0;
  2954.       for (r = 0; r < RLEVELS; r++)
  2955.          for (g = 0; g < GLEVELS; g++)
  2956.             for (b = 0; b < BLEVELS; b++) {
  2957.                int exact;
  2958.                xcol.red   = ( r*65535)/(RLEVELS-1);
  2959.                xcol.green = ( g*65535)/(GLEVELS-1);
  2960.                xcol.blue  = ( b*65535)/(BLEVELS-1);
  2961.                noFaultXAllocColor( display, colormap, ncolors,
  2962.                                    &xcol, &exact );
  2963.                ToglMesaUsedPixelCells[ i++] = xcol.pixel;
  2964.                if (!exact) {
  2965.                   colorsfailed++;
  2966.                }
  2967.             }
  2968.       ToglMesaUsedFreeCells = i;
  2969.  
  2970.       XFreeColors( display, colormap, ToglMesaUsedPixelCells,
  2971.                    ToglMesaUsedFreeCells, 0x00000000);
  2972.    }
  2973.    return ToglMesaUsedFreeCells;
  2974. }
  2975.  
  2976.  
  2977. static void free_default_color_cells( Display *display, Colormap colormap)
  2978. {
  2979.    if ( ToglMesaUsedPixelCells) {
  2980.       XFreeColors( display, colormap, ToglMesaUsedPixelCells,
  2981.                    ToglMesaUsedFreeCells, 0x00000000);
  2982.       free( ( char *)ToglMesaUsedPixelCells);
  2983.       ToglMesaUsedPixelCells = NULL;
  2984.       ToglMesaUsedFreeCells = 0;
  2985.    }
  2986. }
  2987. #endif
  2988.  
  2989.  
  2990. /*
  2991.  * Generate EPS file.
  2992.  * Contributed by Miguel A. De Riera Pasenau (miguel@DALILA.UPC.ES)
  2993.  */
  2994.  
  2995. /* Function that creates a EPS File from a created pixmap on the current
  2996.  * context.
  2997.  * Based on the code from Copyright (c) Mark J. Kilgard, 1996.
  2998.  * Parameters: name_file, b&w / Color flag, redraw function.
  2999.  * The redraw function is needed in order to draw things into the new
  3000.  * created pixmap.
  3001.  */
  3002.  
  3003. /* Copyright (c) Mark J. Kilgard, 1996. */
  3004.  
  3005. static GLvoid *grabPixels(int inColor, unsigned int width, unsigned int height)
  3006. {
  3007.    GLvoid *buffer;
  3008.    GLint swapbytes, lsbfirst, rowlength;
  3009.    GLint skiprows, skippixels, alignment;
  3010.    GLenum format;
  3011.    unsigned int size;
  3012.  
  3013.    if (inColor) {
  3014.       format = GL_RGB;
  3015.       size = width * height * 3;
  3016.    }
  3017.    else {
  3018.       format = GL_LUMINANCE;
  3019.       size = width * height * 1;
  3020.    }
  3021.  
  3022.    buffer = (GLvoid *) malloc(size);
  3023.    if (buffer == NULL)
  3024.       return NULL;
  3025.  
  3026.    /* Save current modes. */
  3027.    glGetIntegerv(GL_PACK_SWAP_BYTES, &swapbytes);
  3028.    glGetIntegerv(GL_PACK_LSB_FIRST, &lsbfirst);
  3029.    glGetIntegerv(GL_PACK_ROW_LENGTH, &rowlength);
  3030.    glGetIntegerv(GL_PACK_SKIP_ROWS, &skiprows);
  3031.    glGetIntegerv(GL_PACK_SKIP_PIXELS, &skippixels);
  3032.    glGetIntegerv(GL_PACK_ALIGNMENT, &alignment);
  3033.    /* Little endian machines (DEC Alpha for example) could
  3034.       benefit from setting GL_PACK_LSB_FIRST to GL_TRUE
  3035.       instead of GL_FALSE, but this would require changing the
  3036.       generated bitmaps too. */
  3037.    glPixelStorei(GL_PACK_SWAP_BYTES, GL_FALSE);
  3038.    glPixelStorei(GL_PACK_LSB_FIRST, GL_FALSE);
  3039.    glPixelStorei(GL_PACK_ROW_LENGTH, 0);
  3040.    glPixelStorei(GL_PACK_SKIP_ROWS, 0);
  3041.    glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
  3042.    glPixelStorei(GL_PACK_ALIGNMENT, 1);
  3043.  
  3044.    /* Actually read the pixels. */
  3045.    glReadPixels(0, 0, width, height, format,
  3046.                 GL_UNSIGNED_BYTE, (GLvoid *) buffer);
  3047.  
  3048.    /* Restore saved modes. */
  3049.    glPixelStorei(GL_PACK_SWAP_BYTES, swapbytes);
  3050.    glPixelStorei(GL_PACK_LSB_FIRST, lsbfirst);
  3051.    glPixelStorei(GL_PACK_ROW_LENGTH, rowlength);
  3052.    glPixelStorei(GL_PACK_SKIP_ROWS, skiprows);
  3053.    glPixelStorei(GL_PACK_SKIP_PIXELS, skippixels);
  3054.    glPixelStorei(GL_PACK_ALIGNMENT, alignment);
  3055.    return buffer;
  3056. }
  3057.  
  3058.  
  3059. static int generateEPS(const char *filename, int inColor,
  3060.                        unsigned int width, unsigned int height)
  3061. {
  3062.    FILE *fp;
  3063.    GLvoid *pixels;
  3064.    unsigned char *curpix;
  3065.    unsigned int components, i;
  3066.    int pos;
  3067.    unsigned char bitpixel;
  3068.  
  3069.    pixels = grabPixels(inColor, width, height);
  3070.    if (pixels == NULL)
  3071.       return 1;
  3072.    if (inColor)
  3073.       components = 3;     /* Red, green, blue. */
  3074.    else
  3075.       components = 1;     /* Luminance. */
  3076.  
  3077.    fp = fopen(filename, "w");
  3078.    if (fp == NULL) {
  3079.       return 2;
  3080.    }
  3081.    fprintf(fp, "%%!PS-Adobe-2.0 EPSF-1.2\n");
  3082.    fprintf(fp, "%%%%Creator: OpenGL pixmap render output\n");
  3083.    fprintf(fp, "%%%%BoundingBox: 0 0 %d %d\n", width, height);
  3084.    fprintf(fp, "%%%%EndComments\n");
  3085.  
  3086.    i = ((( width * height) + 7) / 8 ) / 40; /* # of lines, 40 bytes per line */
  3087.    fprintf(fp, "%%%%BeginPreview: %d %d %d %d\n%%", width, height, 1, i);
  3088.    pos = 0;
  3089.    curpix = ( unsigned char *)pixels;
  3090.    for ( i = 0; i < width * height * components; ) {
  3091.       bitpixel = 0;
  3092.       if ( inColor) {
  3093.          double pix = 0.0;
  3094.          pix = 0.30 * ( double)curpix[ i++] + 0.59 * ( double)curpix[ i++] + 0.11 * ( double)curpix[ i++];
  3095.          if ( pix > 127.0) bitpixel |= 0x80;
  3096.          pix = 0.30 * ( double)curpix[ i++] + 0.59 * ( double)curpix[ i++] + 0.11 * ( double)curpix[ i++];
  3097.          if ( pix > 127.0) bitpixel |= 0x40;
  3098.          pix = 0.30 * ( double)curpix[ i++] + 0.59 * ( double)curpix[ i++] + 0.11 * ( double)curpix[ i++];
  3099.          if ( pix > 127.0) bitpixel |= 0x20;
  3100.          pix = 0.30 * ( double)curpix[ i++] + 0.59 * ( double)curpix[ i++] + 0.11 * ( double)curpix[ i++];
  3101.          if ( pix > 127.0) bitpixel |= 0x10;
  3102.          pix = 0.30 * ( double)curpix[ i++] + 0.59 * ( double)curpix[ i++] + 0.11 * ( double)curpix[ i++];
  3103.          if ( pix > 127.0) bitpixel |= 0x08;
  3104.          pix = 0.30 * ( double)curpix[ i++] + 0.59 * ( double)curpix[ i++] + 0.11 * ( double)curpix[ i++];
  3105.          if ( pix > 127.0) bitpixel |= 0x04;
  3106.          pix = 0.30 * ( double)curpix[ i++] + 0.59 * ( double)curpix[ i++] + 0.11 * ( double)curpix[ i++];
  3107.          if ( pix > 127.0) bitpixel |= 0x02;
  3108.          pix = 0.30 * ( double)curpix[ i++] + 0.59 * ( double)curpix[ i++] + 0.11 * ( double)curpix[ i++];
  3109.          if ( pix > 127.0) bitpixel |= 0x01;
  3110.       }
  3111.       else {
  3112.          if ( curpix[ i++] > 0x7f) bitpixel |= 0x80;
  3113.          if ( curpix[ i++] > 0x7f) bitpixel |= 0x40;
  3114.          if ( curpix[ i++] > 0x7f) bitpixel |= 0x20;
  3115.          if ( curpix[ i++] > 0x7f) bitpixel |= 0x10;
  3116.          if ( curpix[ i++] > 0x7f) bitpixel |= 0x08;
  3117.          if ( curpix[ i++] > 0x7f) bitpixel |= 0x04;
  3118.          if ( curpix[ i++] > 0x7f) bitpixel |= 0x02;
  3119.          if ( curpix[ i++] > 0x7f) bitpixel |= 0x01;
  3120.       }
  3121.       fprintf(fp, "%02hx", bitpixel);
  3122.       if (++pos >= 40) {
  3123.          fprintf(fp, "\n%%");
  3124.          pos = 0;
  3125.       }
  3126.    }
  3127.    if (pos)
  3128.       fprintf(fp, "\n%%%%EndPreview\n");
  3129.    else
  3130.       fprintf(fp, "%%EndPreview\n");
  3131.  
  3132.    fprintf(fp, "gsave\n");
  3133.    fprintf(fp, "/bwproc {\n");
  3134.    fprintf(fp, "    rgbproc\n");
  3135.    fprintf(fp, "    dup length 3 idiv string 0 3 0\n");
  3136.    fprintf(fp, "    5 -1 roll {\n");
  3137.    fprintf(fp, "    add 2 1 roll 1 sub dup 0 eq\n");
  3138.    fprintf(fp, "    { pop 3 idiv 3 -1 roll dup 4 -1 roll dup\n");
  3139.    fprintf(fp, "        3 1 roll 5 -1 roll put 1 add 3 0 }\n");
  3140.    fprintf(fp, "    { 2 1 roll } ifelse\n");
  3141.    fprintf(fp, "    } forall\n");
  3142.    fprintf(fp, "    pop pop pop\n");
  3143.    fprintf(fp, "} def\n");
  3144.    fprintf(fp, "systemdict /colorimage known not {\n");
  3145.    fprintf(fp, "    /colorimage {\n");
  3146.    fprintf(fp, "        pop\n");
  3147.    fprintf(fp, "        pop\n");
  3148.    fprintf(fp, "        /rgbproc exch def\n");
  3149.    fprintf(fp, "        { bwproc } image\n");
  3150.    fprintf(fp, "    } def\n");
  3151.    fprintf(fp, "} if\n");
  3152.    fprintf(fp, "/picstr %d string def\n", width * components);
  3153.    fprintf(fp, "%d %d scale\n", width, height);
  3154.    fprintf(fp, "%d %d %d\n", width, height, 8);
  3155.    fprintf(fp, "[%d 0 0 %d 0 0]\n", width, height);
  3156.    fprintf(fp, "{currentfile picstr readhexstring pop}\n");
  3157.    fprintf(fp, "false %d\n", components);
  3158.    fprintf(fp, "colorimage\n");
  3159.  
  3160.    curpix = (unsigned char *) pixels;
  3161.    pos = 0;
  3162.    for (i = width * height * components; i > 0; i--) {
  3163.       fprintf(fp, "%02hx", *curpix++);
  3164.       if (++pos >= 40) {
  3165.      fprintf(fp, "\n");
  3166.      pos = 0;
  3167.       }
  3168.    }
  3169.    if (pos)
  3170.       fprintf(fp, "\n");
  3171.  
  3172.    fprintf(fp, "grestore\n");
  3173.    free(pixels);
  3174.    fclose(fp);
  3175.    return 0;
  3176. }
  3177.  
  3178.  
  3179. /* int Togl_DumpToEpsFile( const struct Togl *togl, const char *filename,
  3180.                         int inColor, void (*user_redraw)(void)) */
  3181. /* changed by GG */
  3182. int Togl_DumpToEpsFile( const struct Togl *togl, const char *filename,
  3183.                         int inColor, void (*user_redraw)( const struct Togl *))
  3184. {
  3185.    int using_mesa = 0;
  3186. #if 0
  3187.    Pixmap eps_pixmap;
  3188.    GLXPixmap eps_glxpixmap;
  3189.    XVisualInfo *vi = togl->VisInfo;
  3190.    Window win = Tk_WindowId( togl->TkWin);
  3191. #endif
  3192.    Display *dpy = Tk_Display( togl->TkWin);
  3193.    int retval;
  3194.    int scrnum = Tk_ScreenNumber(togl->TkWin);
  3195.    unsigned int width = togl->Width, height = togl->Height;
  3196.  
  3197. #if defined(X11)
  3198.    if (strstr(glXQueryServerString( dpy, scrnum, GLX_VERSION ), "Mesa"))
  3199.       using_mesa = 1;
  3200.    else
  3201. #endif /* X11 */
  3202.       using_mesa = 0;
  3203.    /* I don't use Pixmap do drawn into, because the code should link
  3204.     * with Mesa libraries and OpenGL libraries, and the which library
  3205.     * we use at run time should not matter, but the name of the calls
  3206.     * differs one from another:
  3207.     * MesaGl: glXCreateGLXPixmapMESA( dpy, vi, eps_pixmap, Tk_Colormap(togl->TkWin))
  3208.     * OpenGl: glXCreateGLXPixmap( dpy, vi, eps_pixmap);
  3209.     *
  3210.     * instead of this I read direct from back buffer of the screeen.
  3211.     */
  3212. #if 0
  3213.    eps_pixmap = XCreatePixmap( dpy, win, width, height, vi->depth);
  3214.    if ( using_mesa)
  3215.       eps_glxpixmap = glXCreateGLXPixmapMESA( dpy, vi, eps_pixmap, Tk_Colormap(togl->TkWin));
  3216.    else
  3217.       eps_glxpixmap = glXCreateGLXPixmap( dpy, vi, eps_pixmap);
  3218.  
  3219.    glXMakeCurrent( dpy, eps_glxpixmap, togl->GlCtx);
  3220.    user_redraw();
  3221. #endif
  3222.    if ( !togl->RgbaFlag) {
  3223.  
  3224. #if defined(WIN32)
  3225. /* Due to the lack of a unique inverse mapping from the frame buffer to
  3226.    the logical palette we need a translation map from the complete
  3227.    logical palette. */
  3228.        {
  3229.            int n, i;
  3230.            TkWinColormap *cmap = (TkWinColormap *)Tk_Colormap(togl->TkWin);
  3231.            LPPALETTEENTRY entry = malloc(togl->EpsMapSize * sizeof(PALETTEENTRY));
  3232.            n = GetPaletteEntries(cmap->palette, 0, togl->EpsMapSize, entry);
  3233.            for (i=0; i<n; i++) {
  3234.                togl->EpsRedMap[i] = entry[i].peRed / 255.0;
  3235.                togl->EpsGreenMap[i] = entry[i].peGreen / 255.0;
  3236.                togl->EpsBlueMap[i] = entry[i].peBlue / 255.0;
  3237.            }
  3238.            free(entry);
  3239.        }
  3240. #endif /* WIN32 */
  3241.  
  3242.       glPixelMapfv( GL_PIXEL_MAP_I_TO_R, togl->EpsMapSize, togl->EpsRedMap);
  3243.       glPixelMapfv( GL_PIXEL_MAP_I_TO_G, togl->EpsMapSize, togl->EpsGreenMap);
  3244.       glPixelMapfv( GL_PIXEL_MAP_I_TO_B, togl->EpsMapSize, togl->EpsBlueMap);
  3245.    }
  3246.    /*  user_redraw(); */
  3247.    user_redraw(togl);  /* changed by GG */
  3248.    /* glReadBuffer( GL_FRONT); */
  3249.    /* by default it read GL_BACK in double buffer mode*/
  3250.    glFlush();
  3251.    retval = generateEPS( filename, inColor, width, height);
  3252. #if 0
  3253.    glXMakeCurrent( dpy, win, togl->GlCtx );
  3254.    glXDestroyGLXPixmap( dpy, eps_glxpixmap);
  3255.    XFreePixmap( dpy, eps_pixmap);
  3256. #endif
  3257.    return retval;
  3258. }
  3259.  
  3260. /*
  3261.  * Full screen stereo for SGI graphics
  3262.  * Contributed by Ben Evans (Ben.Evans@anusf.anu.edu.au)
  3263.  * This code was based on SGI's /usr/share/src/OpenGL/teach/stereo
  3264.  */
  3265.  
  3266. #if defined(__sgi) && defined(STEREO)
  3267.  
  3268. static struct stereoStateRec {
  3269.     Bool        useSGIStereo;
  3270.     Display     *currentDisplay;
  3271.     Window      currentWindow;
  3272.     GLXContext  currentContext;
  3273.     GLenum      currentDrawBuffer;
  3274.     int         currentStereoBuffer;
  3275.     Bool        enabled;
  3276.     char        *stereoCommand;
  3277.     char        *restoreCommand;
  3278. } stereo;
  3279.  
  3280. /* call instead of glDrawBuffer */
  3281. void
  3282. Togl_StereoDrawBuffer(GLenum mode)
  3283. {
  3284.   if (stereo.useSGIStereo) {
  3285.     stereo.currentDrawBuffer = mode;
  3286.     switch (mode) {
  3287.     case GL_FRONT:
  3288.     case GL_BACK:
  3289.     case GL_FRONT_AND_BACK:
  3290.       /*
  3291.       ** Simultaneous drawing to both left and right buffers isn't
  3292.       ** really possible if we don't have a stereo capable visual.
  3293.       ** For now just fall through and use the left buffer.
  3294.       */
  3295.     case GL_LEFT:
  3296.     case GL_FRONT_LEFT:
  3297.     case GL_BACK_LEFT:
  3298.       stereo.currentStereoBuffer = STEREO_BUFFER_LEFT;
  3299.       break;
  3300.     case GL_RIGHT:
  3301.     case GL_FRONT_RIGHT: 
  3302.       stereo.currentStereoBuffer = STEREO_BUFFER_RIGHT;
  3303.       mode = GL_FRONT;
  3304.       break;
  3305.     case GL_BACK_RIGHT:
  3306.       stereo.currentStereoBuffer = STEREO_BUFFER_RIGHT;
  3307.       mode = GL_BACK;
  3308.       break;
  3309.     default:
  3310.       break;
  3311.     }
  3312.     if (stereo.currentDisplay && stereo.currentWindow) {
  3313.       glXWaitGL();  /* sync with GL command stream before calling X */
  3314.       XSGISetStereoBuffer(stereo.currentDisplay,
  3315.               stereo.currentWindow,
  3316.               stereo.currentStereoBuffer);
  3317.       glXWaitX();   /* sync with X command stream before calling GL */
  3318.     }
  3319.   }
  3320.   glDrawBuffer(mode);
  3321. }
  3322.  
  3323. /* call instead of glClear */
  3324. void
  3325. Togl_StereoClear(GLbitfield mask)
  3326. {
  3327.   GLenum drawBuffer;
  3328.   if (stereo.useSGIStereo) {
  3329.     drawBuffer = stereo.currentDrawBuffer;
  3330.     switch (drawBuffer) {
  3331.     case GL_FRONT:
  3332.       stereoDrawBuffer(GL_FRONT_RIGHT);
  3333.       glClear(mask);
  3334.       stereoDrawBuffer(drawBuffer);
  3335.       break;
  3336.     case GL_BACK:
  3337.       stereoDrawBuffer(GL_BACK_RIGHT);
  3338.       glClear(mask);
  3339.       stereoDrawBuffer(drawBuffer);
  3340.       break;
  3341.     case GL_FRONT_AND_BACK:
  3342.       stereoDrawBuffer(GL_RIGHT);
  3343.       glClear(mask);
  3344.       stereoDrawBuffer(drawBuffer);
  3345.       break;
  3346.     case GL_LEFT:
  3347.     case GL_FRONT_LEFT:
  3348.     case GL_BACK_LEFT:
  3349.     case GL_RIGHT:
  3350.     case GL_FRONT_RIGHT:
  3351.     case GL_BACK_RIGHT:
  3352.     default:
  3353.       break;
  3354.     }
  3355.   }
  3356.   glClear(mask);
  3357. }
  3358.  
  3359. static void
  3360. stereoMakeCurrent(Display *dpy, Window win, GLXContext ctx)
  3361. {
  3362.   
  3363.   if (stereo.useSGIStereo) {
  3364.     if (dpy && (dpy != stereo.currentDisplay)) {
  3365.       int event, error;
  3366.       /* Make sure new Display supports SGIStereo */
  3367.       if (XSGIStereoQueryExtension(dpy, &event, &error) == False) {
  3368.     dpy = NULL;
  3369.       }
  3370.     }
  3371.     if (dpy && win && (win != stereo.currentWindow)) {
  3372.       /* Make sure new Window supports SGIStereo */
  3373.       if (XSGIQueryStereoMode(dpy, win) == X_STEREO_UNSUPPORTED) {
  3374.     win = None;
  3375.       }
  3376.     }
  3377.     if (ctx && (ctx != stereo.currentContext)) {
  3378.       GLint drawBuffer;
  3379.       glGetIntegerv(GL_DRAW_BUFFER, &drawBuffer);
  3380.       stereoDrawBuffer((GLenum) drawBuffer);
  3381.     }
  3382.     stereo.currentDisplay = dpy;
  3383.     stereo.currentWindow = win;
  3384.     stereo.currentContext = ctx;
  3385.   }
  3386. }
  3387.  
  3388.  
  3389. /* call before using stereo */
  3390. static void
  3391. stereoInit(struct Togl *togl,int stereoEnabled)
  3392. {
  3393.   stereo.useSGIStereo = stereoEnabled;
  3394.   stereo.currentDisplay = NULL;
  3395.   stereo.currentWindow = None;
  3396.   stereo.currentContext = NULL;
  3397.   stereo.currentDrawBuffer = GL_NONE;
  3398.   stereo.currentStereoBuffer = STEREO_BUFFER_NONE;
  3399.   stereo.enabled = False;
  3400. }
  3401.  
  3402.  
  3403. void
  3404. Togl_StereoFrustum(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top,
  3405.                GLfloat near, GLfloat far, GLfloat eyeDist, GLfloat eyeOffset)
  3406. {
  3407.   GLfloat eyeShift = (eyeDist - near) * (eyeOffset / eyeDist);
  3408.   
  3409.   glFrustum(left+eyeShift, right+eyeShift, bottom, top, near, far);
  3410.   glTranslatef(-eyeShift, 0.0, 0.0);
  3411. }
  3412.  
  3413. #endif /* __sgi STEREO */
  3414.