Revision: 76995
          http://sourceforge.net/p/brlcad/code/76995
Author:   starseeker
Date:     2020-08-31 18:05:39 +0000 (Mon, 31 Aug 2020)
Log Message:
-----------
Start Tk dm with glx dm, changing only the names, so we start with a working 
state.

Modified Paths:
--------------
    brlcad/branches/swrast/src/libdm/glx/CMakeLists.txt
    brlcad/branches/swrast/src/libdm/tk/CMakeLists.txt
    brlcad/branches/swrast/src/libdm/tk/dm-tk.c
    brlcad/branches/swrast/src/libdm/tk/dm-tk.h
    brlcad/branches/swrast/src/libdm/tk/if_tk.c

Added Paths:
-----------
    brlcad/branches/swrast/src/libdm/tk/fb_tk.h

Removed Paths:
-------------
    brlcad/branches/swrast/src/libdm/glx/dm-glx.h

Modified: brlcad/branches/swrast/src/libdm/glx/CMakeLists.txt
===================================================================
--- brlcad/branches/swrast/src/libdm/glx/CMakeLists.txt 2020-08-31 08:06:33 UTC 
(rev 76994)
+++ brlcad/branches/swrast/src/libdm/glx/CMakeLists.txt 2020-08-31 18:05:39 UTC 
(rev 76995)
@@ -39,7 +39,6 @@
 CMAKEFILES(
   CMakeLists.txt
   ${OGL_SRCS}
-  dm-glx.h
   dm-ogl.h
   fb_ogl.h
   )

Deleted: brlcad/branches/swrast/src/libdm/glx/dm-glx.h
===================================================================
--- brlcad/branches/swrast/src/libdm/glx/dm-glx.h       2020-08-31 08:06:33 UTC 
(rev 76994)
+++ brlcad/branches/swrast/src/libdm/glx/dm-glx.h       2020-08-31 18:05:39 UTC 
(rev 76995)
@@ -1,87 +0,0 @@
-/*                          D M - G L X . H
- * BRL-CAD
- *
- * Copyright (c) 1993-2020 United States Government as represented by
- * the U.S. Army Research Laboratory.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * version 2.1 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this file; see the file named COPYING for more
- * information.
- */
-/** @addtogroup libstruct dm */
-/** @{ */
-/** @file dm-glx.h
- *
- */
-
-#ifndef DM_GLX_H
-#define DM_GLX_H
-
-#include "common.h"
-
-/* Map +/-2048 GED space into -1.0..+1.0 :: x/2048*/
-#define GED2IRIS(x)    (((float)(x))*0.00048828125)
-
-#define Glx_MV_O(_m) offsetof(struct modifiable_glx_vars, _m)
-
-struct modifiable_glx_vars {
-    int cueing_on;
-    int zclipping_on;
-    int zbuffer_on;
-    int lighting_on;
-    int debug;
-    int zbuf;
-    int rgb;
-    int doublebuffer;
-    int min_scr_z;       /* based on getgdesc(GD_ZMIN) */
-    int max_scr_z;       /* based on getgdesc(GD_ZMAX) */
-};
-
-struct glx_vars {
-    struct bu_list l;
-    Display *dpy;
-    Window win;
-    Tk_Window top;
-    Tk_Window xtkwin;
-    int depth;
-    int omx, omy;
-    unsigned int mb_mask;
-    Colormap cmap;
-    XVisualInfo *vip;
-    int devmotionnotify;
-    int devbuttonpress;
-    int devbuttonrelease;
-    int knobs[8];
-    int stereo_is_on;
-    int is_gt;
-    struct modifiable_glx_vars mvars;
-};
-
-__BEGIN_DECLS
-
-extern void glx_clearToBlack();
-extern struct glx_vars head_glx_vars;
-
-__END_DECLS
-
-#endif /* DM_GLX_H */
-
-/** @} */
-/*
- * Local Variables:
- * mode: C
- * tab-width: 8
- * indent-tabs-mode: t
- * c-file-style: "stroustrup"
- * End:
- * ex: shiftwidth=4 tabstop=8
- */

Modified: brlcad/branches/swrast/src/libdm/tk/CMakeLists.txt
===================================================================
--- brlcad/branches/swrast/src/libdm/tk/CMakeLists.txt  2020-08-31 08:06:33 UTC 
(rev 76994)
+++ brlcad/branches/swrast/src/libdm/tk/CMakeLists.txt  2020-08-31 18:05:39 UTC 
(rev 76995)
@@ -6,6 +6,8 @@
 if(BRLCAD_ENABLE_TK AND BRLCAD_ENABLE_DM_TK)
 
   find_package(TCL)
+  find_package(X11)
+  find_package(GL)
 
   include_directories(
     ${CMAKE_CURRENT_SOURCE_DIR}
@@ -12,17 +14,20 @@
     ${BRLCAD_BINARY_DIR}/include
     ${BRLCAD_SOURCE_DIR}/include
     ${BU_INCLUDE_DIRS}
+    ${X11_INCLUDE_DIR}
+    ${OPENGL_INCLUDE_DIR_GL}
+    ${OPENGL_INCLUDE_DIR_GLX}
     ${TCL_INCLUDE_PATH}
     ${TK_INCLUDE_PATH}
     )
 
   set_property(SOURCE dm-tk.c APPEND PROPERTY COMPILE_DEFINITIONS 
FB_USE_INTERNAL_API)
-  set_property(SOURCE if_tk24.c APPEND PROPERTY COMPILE_DEFINITIONS 
FB_USE_INTERNAL_API)
+  set_property(SOURCE if_tk.c APPEND PROPERTY COMPILE_DEFINITIONS 
FB_USE_INTERNAL_API)
 
   add_definitions(-DDM_PLUGIN)
 
   dm_plugin_library(dm-tk SHARED ${TK_SRCS})
-  target_link_libraries(dm-tk libdm libbu ${TCL_LIBRARY} ${TK_LIBRARY})
+  target_link_libraries(dm-tk libdm libbu ${X11_LIBRARIES} ${OPENGL_LIBRARIES} 
${TCL_LIBRARY} ${TK_LIBRARY})
   set_property(TARGET dm-tk APPEND PROPERTY COMPILE_DEFINITIONS BRLCADBUILD 
HAVE_CONFIG_H)
   VALIDATE_STYLE(dm-tk "${TK_SRCS}")
 

Modified: brlcad/branches/swrast/src/libdm/tk/dm-tk.c
===================================================================
--- brlcad/branches/swrast/src/libdm/tk/dm-tk.c 2020-08-31 08:06:33 UTC (rev 
76994)
+++ brlcad/branches/swrast/src/libdm/tk/dm-tk.c 2020-08-31 18:05:39 UTC (rev 
76995)
@@ -1,4 +1,4 @@
-/*                          D M - T K . C
+/*                        D M - T K . C
  * BRL-CAD
  *
  * Copyright (c) 1988-2020 United States Government as represented by
@@ -19,7 +19,7 @@
  */
 /** @file libdm/dm-tk.c
  *
- * A Display Manager that should work wherever tk does.
+ * A Tk Mesa3d Display Manager.
  *
  */
 
@@ -27,52 +27,669 @@
 
 #include <stdlib.h>
 #include <stdio.h>
-#include <limits.h>
+#include <math.h>
 #include <string.h>
 
-/* FIXME: suboptimal, just picked the first mac-specific config symbol
- * encountered to know when to turn on the AquaTk X bindings from Tk.
- */
-#ifdef HAVE_MACH_THREAD_POLICY_H
-#  define MAC_OSX_TK 1
-#endif
 
-/* Even on a platform that has no real X, I should be able to use the
- * Xutil that comes with Tk
- */
-#include <tk.h>
-#include <X11/Xutil.h>
-#include <X11/X.h>
-
 #ifdef HAVE_X11_XOSDEFS_H
 #  include <X11/Xfuncproto.h>
 #  include <X11/Xosdefs.h>
 #endif
-
-#if defined(linux)
+#ifdef linux
 #  undef X_NOT_STDC_ENV
 #  undef X_NOT_POSIX
 #endif
 
+#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
+#  include <X11/extensions/XInput.h>
+#endif /* HAVE_X11_XINPUT_H */
+
+/* glx.h on Mac OS X (and perhaps elsewhere) defines a slew of
+ * parameter names that shadow system symbols.  protect the system
+ * symbols by redefining the parameters prior to header inclusion.
+ */
+#define j1 J1
+#define y1 Y1
+#define read rd
+#define index idx
+#define access acs
+#define remainder rem
+#ifdef HAVE_GL_GLX_H
+#  include <GL/glx.h>
+#  ifdef HAVE_XRENDER
+#    include <X11/extensions/Xrender.h>
+#  endif
+#endif
+#ifdef HAVE_GL_GL_H
+#  include <GL/gl.h>
+#endif
+
+#undef remainder
+#undef access
+#undef index
+#undef read
+#undef y1
+#undef j1
+
+#include "png.h"
+
+#include "tk.h"
+
+#undef VMIN            /* is used in vmath.h, too */
+
 #include "vmath.h"
 #include "bn.h"
+#include "rt/solid.h"
 #include "dm.h"
+#include "../null/dm-Null.h"
+#include "./fb_tk.h"
 #include "./dm-tk.h"
-#include "../null/dm-Null.h"
+
 #include "../include/private.h"
-#include "rt/solid.h"
 
+#define ENABLE_POINT_SMOOTH 1
+
+#define VIEWFACTOR      (1.0/(*dmp->i->dm_vp))
+#define VIEWSIZE        (2.0*(*dmp->i->dm_vp))
+
+/* these are from /usr/include/gl.h could be device dependent */
+#define XMAXSCREEN     1279
+#define YMAXSCREEN     1023
+#define YSTEREO                491     /* subfield height, in scanlines */
+#define YOFFSET_LEFT   532     /* YSTEREO + YBLANK ? */
+
+HIDDEN XVisualInfo *tk_choose_visual(struct dm *dmp, Tk_Window tkwin);
+
+/* Display Manager package interface */
+#define IRBOUND 4095.9 /* Max magnification in Rot matrix */
 #define PLOTBOUND 1000.0       /* Max magnification in Rot matrix */
 
-#define vectorThreshold 100000
+struct dm *tk_open(void *vinterp, int argc, const char **argv);
+HIDDEN int tk_close(struct dm *dmp);
+HIDDEN int tk_drawBegin(struct dm *dmp);
+HIDDEN int tk_drawEnd(struct dm *dmp);
+HIDDEN int tk_normal(struct dm *dmp);
+HIDDEN int tk_loadMatrix(struct dm *dmp, fastf_t *mat, int which_eye);
+HIDDEN int tk_loadPMatrix(struct dm *dmp, fastf_t *mat);
+HIDDEN int tk_drawString2D(struct dm *dmp, const char *str, fastf_t x, fastf_t 
y, int size, int use_aspect);
+HIDDEN int tk_drawLine2D(struct dm *dmp, fastf_t X1, fastf_t Y1, fastf_t X2, 
fastf_t Y2);
+HIDDEN int tk_drawLine3D(struct dm *dmp, point_t pt1, point_t pt2);
+HIDDEN int tk_drawLines3D(struct dm *dmp, int npoints, point_t *points, int 
sflag);
+HIDDEN int tk_drawPoint2D(struct dm *dmp, fastf_t x, fastf_t y);
+HIDDEN int tk_drawPoint3D(struct dm *dmp, point_t point);
+HIDDEN int tk_drawPoints3D(struct dm *dmp, int npoints, point_t *points);
+HIDDEN int tk_drawVList(struct dm *dmp, register struct bn_vlist *vp);
+HIDDEN int tk_drawVListHiddenLine(struct dm *dmp, register struct bn_vlist 
*vp);
+HIDDEN int tk_draw(struct dm *dmp, struct bn_vlist *(*callback_function)(void 
*), void **data);
+HIDDEN int tk_setFGColor(struct dm *dmp, unsigned char r, unsigned char g, 
unsigned char b, int strict, fastf_t transparency);
+HIDDEN int tk_setBGColor(struct dm *dmp, unsigned char r, unsigned char g, 
unsigned char b);
+HIDDEN int tk_setLineAttr(struct dm *dmp, int width, int style);
+HIDDEN int tk_configureWin_guts(struct dm *dmp, int force);
+HIDDEN int tk_configureWin(struct dm *dmp, int force);
+HIDDEN int tk_setLight(struct dm *dmp, int lighting_on);
+HIDDEN int tk_setTransparency(struct dm *dmp, int transparency_on);
+HIDDEN int tk_setDepthMask(struct dm *dmp, int depthMask_on);
+HIDDEN int tk_setZBuffer(struct dm *dmp, int zbuffer_on);
+HIDDEN int tk_setWinBounds(struct dm *dmp, fastf_t *w);
+HIDDEN int tk_debug(struct dm *dmp, int vl);
+HIDDEN int tk_logfile(struct dm *dmp, const char *filename);
+HIDDEN int tk_beginDList(struct dm *dmp, unsigned int list);
+HIDDEN int tk_endDList(struct dm *dmp);
+HIDDEN int tk_drawDList(unsigned int list);
+HIDDEN int tk_freeDLists(struct dm *dmp, unsigned int list, int range);
+HIDDEN int tk_genDLists(struct dm *dmp, size_t range);
+HIDDEN int tk_getDisplayImage(struct dm *dmp, unsigned char **image);
+HIDDEN int tk_reshape(struct dm *dmp, int width, int height);
+HIDDEN int tk_makeCurrent(struct dm *dmp);
 
-static fastf_t min_short = (fastf_t)SHRT_MIN;
-static fastf_t max_short = (fastf_t)SHRT_MAX;
 
-static int tk_close(struct dm *dmp);
-static int tk_configureWin_guts(struct dm *dmp, int force);
+static fastf_t default_viewscale = 1000.0;
+static double xlim_view = 1.0; /* args for glOrtho*/
+static double ylim_view = 1.0;
 
+/* lighting parameters */
+static float amb_three[] = {0.3, 0.3, 0.3, 1.0};
+
+static float light0_position[] = {0.0, 0.0, 1.0, 0.0};
+static float light0_diffuse[] = {1.0, 1.0, 1.0, 1.0}; /* white */
+static float wireColor[4];
+static float ambientColor[4];
+static float specularColor[4];
+static float diffuseColor[4];
+static float backDiffuseColorDark[4];
+static float backDiffuseColorLight[4];
+
+HIDDEN void
+tk_printmat(struct bu_vls *tmp_vls, fastf_t *mat) {
+    bu_vls_printf(tmp_vls, "%g %g %g %g\n", mat[0], mat[4], mat[8], mat[12]);
+    bu_vls_printf(tmp_vls, "%g %g %g %g\n", mat[1], mat[5], mat[9], mat[13]);
+    bu_vls_printf(tmp_vls, "%g %g %g %g\n", mat[2], mat[6], mat[10], mat[14]);
+    bu_vls_printf(tmp_vls, "%g %g %g %g\n", mat[3], mat[7], mat[11], mat[15]);
+}
+
+HIDDEN void
+tk_printglmat(struct bu_vls *tmp_vls, GLfloat *m) {
+    bu_vls_printf(tmp_vls, "%g %g %g %g\n", m[0], m[4], m[8], m[12]);
+    bu_vls_printf(tmp_vls, "%g %g %g %g\n", m[1], m[5], m[9], m[13]);
+    bu_vls_printf(tmp_vls, "%g %g %g %g\n", m[2], m[6], m[10], m[14]);
+    bu_vls_printf(tmp_vls, "%g %g %g %g\n", m[3], m[7], m[11], m[15]);
+}
+
+
+void
+tk_fogHint(struct dm *dmp, int fastfog)
+{
+    struct modifiable_tk_vars *mvars = (struct modifiable_tk_vars 
*)dmp->i->m_vars;
+    mvars->fastfog = fastfog;
+    glHint(GL_FOG_HINT, fastfog ? GL_FASTEST : GL_NICEST);
+}
+
+
+HIDDEN int
+tk_setBGColor(struct dm *dmp, unsigned char r, unsigned char g, unsigned char 
b)
+{
+    struct modifiable_tk_vars *mvars = (struct modifiable_tk_vars 
*)dmp->i->m_vars;
+    struct dm_tkvars *pubvars = (struct dm_tkvars *)dmp->i->dm_vars.pub_vars;
+    struct tk_vars *privars = (struct tk_vars *)dmp->i->dm_vars.priv_vars;
+    if (dmp->i->dm_debugLevel == 1)
+       bu_log("tk_setBGColor()\n");
+
+    dmp->i->dm_bg[0] = r;
+    dmp->i->dm_bg[1] = g;
+    dmp->i->dm_bg[2] = b;
+
+    privars->r = r / 255.0;
+    privars->g = g / 255.0;
+    privars->b = b / 255.0;
+
+    if (mvars->doublebuffer) {
+       glXSwapBuffers(pubvars->dpy,
+                      pubvars->win);
+       glClearColor(privars->r,
+                    privars->g,
+                    privars->b,
+                    0.0);
+       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+    }
+
+    return BRLCAD_OK;
+}
+
+
 /*
+ * Either initially, or on resize/reshape of the window,
+ * sense the actual size of the window, and perform any
+ * other initializations of the window configuration.
+ *
+ * also change font size if necessary
+ */
+HIDDEN int
+tk_configureWin_guts(struct dm *dmp, int force)
+{
+    XWindowAttributes xwa;
+    XFontStruct *newfontstruct;
+
+    struct dm_tkvars *pubvars = (struct dm_tkvars *)dmp->i->dm_vars.pub_vars;
+    struct tk_vars *privars = (struct tk_vars *)dmp->i->dm_vars.priv_vars;
+
+    if (dmp->i->dm_debugLevel)
+       bu_log("tk_configureWin_guts()\n");
+
+    XGetWindowAttributes(pubvars->dpy,
+                        pubvars->win, &xwa);
+
+    /* nothing to do */
+    if (!force &&
+       dmp->i->dm_height == xwa.height &&
+       dmp->i->dm_width == xwa.width)
+       return BRLCAD_OK;
+
+    tk_reshape(dmp, xwa.width, xwa.height);
+
+    /* First time through, load a font or quit */
+    if (pubvars->fontstruct == NULL) {
+       if ((pubvars->fontstruct =
+            XLoadQueryFont(pubvars->dpy,
+                           FONT9)) == NULL) {
+           /* Try hardcoded backup font */
+           if ((pubvars->fontstruct =
+                XLoadQueryFont(pubvars->dpy,
+                               FONTBACK)) == NULL) {
+               bu_log("tk_configureWin_guts: Can't open font '%s' or '%s'\n", 
FONT9, FONTBACK);
+               return BRLCAD_ERROR;
+           }
+       }
+       glXUseXFont(pubvars->fontstruct->fid,
+                   0, 127, privars->fontOffset);
+    }
+
+    if (DM_VALID_FONT_SIZE(dmp->i->dm_fontsize)) {
+       if (pubvars->fontstruct->per_char->width != dmp->i->dm_fontsize) {
+           if ((newfontstruct = XLoadQueryFont(pubvars->dpy,
+                                               
DM_FONT_SIZE_TO_NAME(dmp->i->dm_fontsize))) != NULL) {
+               XFreeFont(pubvars->dpy,
+                         pubvars->fontstruct);
+               pubvars->fontstruct = newfontstruct;
+               glXUseXFont(pubvars->fontstruct->fid,
+                           0, 127, privars->fontOffset);
+           }
+       }
+    } else {
+       /* Always try to choose a the font that best fits the window size.
+        */
+
+       if (dmp->i->dm_width < 582) {
+           if (pubvars->fontstruct->per_char->width != 5) {
+               if ((newfontstruct = XLoadQueryFont(pubvars->dpy,
+                                                   FONT5)) != NULL) {
+                   XFreeFont(pubvars->dpy,
+                             pubvars->fontstruct);
+                   pubvars->fontstruct = newfontstruct;
+                   glXUseXFont(pubvars->fontstruct->fid,
+                               0, 127, privars->fontOffset);
+               }
+           }
+       } else if (dmp->i->dm_width < 679) {
+           if (pubvars->fontstruct->per_char->width != 6) {
+               if ((newfontstruct = XLoadQueryFont(pubvars->dpy,
+                                                   FONT6)) != NULL) {
+                   XFreeFont(pubvars->dpy,
+                             pubvars->fontstruct);
+                   pubvars->fontstruct = newfontstruct;
+                   glXUseXFont(pubvars->fontstruct->fid,
+                               0, 127, privars->fontOffset);
+               }
+           }
+       } else if (dmp->i->dm_width < 776) {
+           if (pubvars->fontstruct->per_char->width != 7) {
+               if ((newfontstruct = XLoadQueryFont(pubvars->dpy,
+                                                   FONT7)) != NULL) {
+                   XFreeFont(pubvars->dpy,
+                             pubvars->fontstruct);
+                   pubvars->fontstruct = newfontstruct;
+                   glXUseXFont(pubvars->fontstruct->fid,
+                               0, 127, privars->fontOffset);
+               }
+           }
+       } else if (dmp->i->dm_width < 873) {
+           if (pubvars->fontstruct->per_char->width != 8) {
+               if ((newfontstruct = XLoadQueryFont(pubvars->dpy,
+                                                   FONT8)) != NULL) {
+                   XFreeFont(pubvars->dpy,
+                             pubvars->fontstruct);
+                   pubvars->fontstruct = newfontstruct;
+                   glXUseXFont(pubvars->fontstruct->fid,
+                               0, 127, privars->fontOffset);
+               }
+           }
+       } else if (dmp->i->dm_width < 1455) {
+           if (pubvars->fontstruct->per_char->width != 9) {
+               if ((newfontstruct = XLoadQueryFont(pubvars->dpy,
+                                                   FONT9)) != NULL) {
+                   XFreeFont(pubvars->dpy,
+                             pubvars->fontstruct);
+                   pubvars->fontstruct = newfontstruct;
+                   glXUseXFont(pubvars->fontstruct->fid,
+                               0, 127, privars->fontOffset);
+               }
+           }
+       } else if (dmp->i->dm_width < 2037) {
+           if (pubvars->fontstruct->per_char->width != 10) {
+               if ((newfontstruct = XLoadQueryFont(pubvars->dpy,
+                                                   FONT10)) != NULL) {
+                   XFreeFont(pubvars->dpy,
+                             pubvars->fontstruct);
+                   pubvars->fontstruct = newfontstruct;
+                   glXUseXFont(pubvars->fontstruct->fid,
+                               0, 127, privars->fontOffset);
+               }
+           }
+       } else {
+           if (pubvars->fontstruct->per_char->width != 12) {
+               if ((newfontstruct = XLoadQueryFont(pubvars->dpy,
+                                                   FONT12)) != NULL) {
+                   XFreeFont(pubvars->dpy,
+                             pubvars->fontstruct);
+                   pubvars->fontstruct = newfontstruct;
+                   glXUseXFont(pubvars->fontstruct->fid,
+                               0, 127, privars->fontOffset);
+               }
+           }
+       }
+    }
+
+    return BRLCAD_OK;
+}
+
+
+HIDDEN int
+tk_reshape(struct dm *dmp, int width, int height)
+{
+    GLint mm;
+
+    struct tk_vars *privars = (struct tk_vars *)dmp->i->dm_vars.priv_vars;
+
+    dmp->i->dm_height = height;
+    dmp->i->dm_width = width;
+    dmp->i->dm_aspect = (fastf_t)dmp->i->dm_width / (fastf_t)dmp->i->dm_height;
+
+    if (dmp->i->dm_debugLevel) {
+       GLfloat m[16];
+       bu_log("tk_reshape()\n");
+       bu_log("width = %d, height = %d\n", dmp->i->dm_width, 
dmp->i->dm_height);
+       glGetFloatv (GL_MODELVIEW_MATRIX, m);
+       glGetFloatv (GL_PROJECTION_MATRIX, m);
+    }
+
+    glViewport(0, 0, dmp->i->dm_width, dmp->i->dm_height);
+
+    glClearColor(privars->r,
+                privars->g,
+                privars->b,
+                0.0);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+    glGetIntegerv(GL_MATRIX_MODE, &mm);
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    glOrtho(-xlim_view, xlim_view, -ylim_view, ylim_view, 
dmp->i->dm_clipmin[2], dmp->i->dm_clipmax[2]);
+    glMatrixMode(mm);
+
+    return 0;
+}
+
+
+HIDDEN int
+tk_makeCurrent(struct dm *dmp)
+{
+    struct dm_tkvars *pubvars = (struct dm_tkvars *)dmp->i->dm_vars.pub_vars;
+    struct tk_vars *privars = (struct tk_vars *)dmp->i->dm_vars.priv_vars;
+
+    if (dmp->i->dm_debugLevel)
+       bu_log("tk_makeCurrent()\n");
+
+    if (!glXMakeCurrent(pubvars->dpy,
+                       pubvars->win,
+                       privars->glxc)) {
+       bu_log("tk_makeCurrent: Couldn't make context current\n");
+       return BRLCAD_ERROR;
+    }
+
+    return BRLCAD_OK;
+}
+
+HIDDEN int
+tk_doevent(struct dm *dmp, void *UNUSED(vclientData), void *veventPtr)
+{
+    XEvent *eventPtr= (XEvent *)veventPtr;
+    if (eventPtr->type == Expose && eventPtr->xexpose.count == 0) {
+       (void)dm_make_current(dmp);
+       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+       dm_set_dirty(dmp, 1);
+       return TCL_OK;
+    }
+    /* allow further processing of this event */
+    return TCL_OK;
+}
+
+HIDDEN int
+tk_configureWin(struct dm *dmp, int force)
+{
+    struct dm_tkvars *pubvars = (struct dm_tkvars *)dmp->i->dm_vars.pub_vars;
+    struct tk_vars *privars = (struct tk_vars *)dmp->i->dm_vars.priv_vars;
+
+    if (!glXMakeCurrent(pubvars->dpy,
+                       pubvars->win,
+                       privars->glxc)) {
+       bu_log("tk_configureWin: Couldn't make context current\n");
+       return BRLCAD_ERROR;
+    }
+
+    return tk_configureWin_guts(dmp, force);
+}
+
+
+HIDDEN int
+tk_setLight(struct dm *dmp, int lighting_on)
+{
+    struct modifiable_tk_vars *mvars = (struct modifiable_tk_vars 
*)dmp->i->m_vars;
+    if (dmp->i->dm_debugLevel)
+       bu_log("tk_setLight()\n");
+
+    dmp->i->dm_light = lighting_on;
+    mvars->lighting_on = dmp->i->dm_light;
+
+    if (!dmp->i->dm_light) {
+       /* Turn it off */
+       glDisable(GL_LIGHTING);
+    } else {
+       /* Turn it on */
+
+       if (1 < dmp->i->dm_light)
+           glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
+       else
+           glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
+
+       glLightModelfv(GL_LIGHT_MODEL_AMBIENT, amb_three);
+       glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);
+
+       glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
+       glLightfv(GL_LIGHT0, GL_SPECULAR, light0_diffuse);
+
+       glEnable(GL_LIGHTING);
+       glEnable(GL_LIGHT0);
+    }
+
+    return BRLCAD_OK;
+}
+
+
+/**
+ * currently, get a double buffered rgba visual that works with Tk and
+ * OpenGL
+ */
+HIDDEN XVisualInfo *
+tk_choose_visual(struct dm *dmp, Tk_Window tkwin)
+{
+    struct dm_tkvars *pubvars = (struct dm_tkvars *)dmp->i->dm_vars.pub_vars;
+    struct modifiable_tk_vars *mvars = (struct modifiable_tk_vars 
*)dmp->i->m_vars;
+    XVisualInfo *vip, vitemp, *vibase, *maxvip;
+    int tries, baddepth;
+    int num, i, j;
+    int fail;
+    int *good = NULL;
+
+    /* requirements */
+    int screen;
+    int use;
+    int rgba;
+    int dbfr;
+
+    /* desires */
+    int m_zbuffer = 1; /* m_zbuffer - try to get zbuffer */
+    int zbuffer;
+
+    int m_stereo; /* m_stereo - try to get stereo */
+    int stereo;
+
+    if (dmp->i->dm_stereo) {
+       m_stereo = 1;
+    } else {
+       m_stereo = 0;
+    }
+
+    memset((void *)&vitemp, 0, sizeof(XVisualInfo));
+    /* Try to satisfy the above desires with a color visual of the
+     * greatest depth */
+
+    vibase = XGetVisualInfo(pubvars->dpy,
+                           0, &vitemp, &num);
+    screen = DefaultScreen(pubvars->dpy);
+
+    good = (int *)bu_malloc(sizeof(int)*num, "alloc good visuals");
+
+    while (1) {
+       for (i=0, j=0, vip=vibase; i<num; i++, vip++) {
+           /* requirements */
+           if (vip->screen != screen)
+               continue;
+
+           fail = glXGetConfig(pubvars->dpy,
+                               vip, GLX_USE_GL, &use);
+           if (fail || !use)
+               continue;
+
+           fail = glXGetConfig(pubvars->dpy,
+                               vip, GLX_RGBA, &rgba);
+           if (fail || !rgba)
+               continue;
+
+           fail = glXGetConfig(pubvars->dpy,
+                               vip, GLX_DOUBLEBUFFER, &dbfr);
+           if (fail || !dbfr)
+               continue;
+
+#ifdef HAVE_XRENDER
+           // https://stackoverflow.com/a/23836430
+           XRenderPictFormat *pict_format = 
XRenderFindVisualFormat(pubvars->dpy, vip->visual);
+           if(pict_format->direct.alphaMask > 0) {
+               //printf("skipping visual with alphaMask\n");
+               continue;
+           }
+#endif
+
+           /* desires */
+           if (m_zbuffer) {
+               fail = glXGetConfig(pubvars->dpy,
+                                   vip, GLX_DEPTH_SIZE, &zbuffer);
+               if (fail || !zbuffer)
+                   continue;
+           }
+
+           if (m_stereo) {
+               fail = glXGetConfig(pubvars->dpy,
+                                   vip, GLX_STEREO, &stereo);
+               if (fail || !stereo) {
+                   bu_log("tk_choose_visual: failed visual - GLX_STEREO\n");
+                   continue;
+               }
+           }
+
+           /* this visual meets criteria */
+           good[j++] = i;
+       }
+
+       /* j = number of acceptable visuals under consideration */
+       if (j >= 1) {
+           baddepth = 1000;
+           for (tries = 0; tries < j; ++tries) {
+               maxvip = vibase + good[0];
+               for (i=1; i<j; i++) {
+                   vip = vibase + good[i];
+                   if ((vip->depth > maxvip->depth)&&(vip->depth < baddepth)) {
+                       maxvip = vip;
+                   }
+               }
+
+               pubvars->cmap =
+                   XCreateColormap(pubvars->dpy,
+                                   RootWindow(pubvars->dpy,
+                                              maxvip->screen), maxvip->visual, 
AllocNone);
+
+               if (Tk_SetWindowVisual(tkwin,
+                                      maxvip->visual, maxvip->depth,
+                                      pubvars->cmap)) {
+
+                   glXGetConfig(pubvars->dpy,
+                                maxvip, GLX_DEPTH_SIZE,
+                                &mvars->depth);
+                   if (mvars->depth > 0)
+                       mvars->zbuf = 1;
+
+                   bu_free(good, "dealloc good visuals");
+                   return maxvip; /* success */
+               } else {
+                   /* retry with lesser depth */
+                   baddepth = maxvip->depth;
+                   XFreeColormap(pubvars->dpy,
+                                 pubvars->cmap);
+               }
+           }
+       }
+
+       /* if no success at this point, relax a desire and try again */
+
+       if (m_stereo) {
+           m_stereo = 0;
+           bu_log("Stereo not available.\n");
+           continue;
+       }
+
+       if (m_zbuffer) {
+           m_zbuffer = 0;
+           continue;
+       }
+
+       /* ran out of visuals, give up */
+       break;
+    }
+
+    bu_free(good, "dealloc good visuals");
+    return (XVisualInfo *)NULL; /* failure */
+}
+
+
+/*
+ * Gracefully release the display.
+ */
+HIDDEN int
+tk_close(struct dm *dmp)
+{
+    struct dm_tkvars *pubvars = (struct dm_tkvars *)dmp->i->dm_vars.pub_vars;
+    struct tk_vars *privars = (struct tk_vars *)dmp->i->dm_vars.priv_vars;
+
+    if (pubvars->dpy) {
+       if (privars->glxc) {
+           glXMakeCurrent(pubvars->dpy, None, NULL);
+           glXDestroyContext(pubvars->dpy,
+                             privars->glxc);
+       }
+
+       if (pubvars->cmap)
+           XFreeColormap(pubvars->dpy,
+                         pubvars->cmap);
+
+       if (pubvars->xtkwin)
+           Tk_DestroyWindow(pubvars->xtkwin);
+    }
+
+    bu_vls_free(&dmp->i->dm_pathName);
+    bu_vls_free(&dmp->i->dm_tkName);
+    bu_vls_free(&dmp->i->dm_dName);
+    bu_free(dmp->i->dm_vars.priv_vars, "tk_close: tk_vars");
+    bu_free(dmp->i->dm_vars.pub_vars, "tk_close: dm_tkvars");
+    BU_PUT(dmp->i, struct dm_impl);
+    BU_PUT(dmp, struct dm);
+
+    return BRLCAD_OK;
+}
+
+int
+tk_viable(const char *dpy_string)
+{
+    Display *dpy;
+    int return_val;
+    if ((dpy = XOpenDisplay(dpy_string)) != NULL) {
+       if (XQueryExtension(dpy, "GLX", &return_val, &return_val, &return_val)) 
{
+           XCloseDisplay(dpy);
+           return 1;
+       }
+       XCloseDisplay(dpy);
+    }
+    return -1;
+}
+
+/*
  * Fire up the display manager, and the display processor.
  *
  */
@@ -80,39 +697,71 @@
 tk_open(void *vinterp, int argc, const char **argv)
 {
     static int count = 0;
+    GLfloat backgnd[4];
     int make_square = -1;
-    XGCValues gcv;
     Tcl_Interp *interp = (Tcl_Interp *)vinterp;
 
+#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
+    int j, k;
+    int ndevices;
+    int nclass = 0;
+    int unused;
+    XDeviceInfoPtr olist = NULL, list = NULL;
+    XDevice *dev = NULL;
+    XEventClass e_class[15];
+    XInputClassInfo *cip;
+#endif
+
     struct bu_vls str = BU_VLS_INIT_ZERO;
     struct bu_vls init_proc_vls = BU_VLS_INIT_ZERO;
+    Display *tmp_dpy = (Display *)NULL;
     struct dm *dmp = NULL;
-    struct dm_impl *dmp_impl = NULL;
-    Tk_Window tkwin;
-    Display *dpy = (Display *)NULL;
-    XColor fg, bg;
+    struct dm_impl *dmpi = NULL;
+    struct modifiable_tk_vars *mvars = NULL;
+    Tk_Window tkwin = (Tk_Window)NULL;
+    int screen_number = -1;
 
-    INIT_XCOLOR(&fg);
-    INIT_XCOLOR(&bg);
+    struct dm_tkvars *pubvars = NULL;
+    struct tk_vars *privvars = NULL;
 
     if ((tkwin = Tk_MainWindow(interp)) == NULL) {
        return DM_NULL;
     }
 
-    BU_ALLOC(dmp, struct dm);
+    BU_GET(dmp, struct dm);
     dmp->magic = DM_MAGIC;
 
-    BU_ALLOC(dmp_impl, struct dm_impl);
+    BU_GET(dmpi, struct dm_impl);
+    *dmpi = *dm_tk.i; /* struct copy */
+    dmp->i = dmpi;
 
-    *dmp_impl = *dm_tk.i; /* struct copy */
-    dmp->i = dmp_impl;
     dmp->i->dm_interp = interp;
+    dmp->i->dm_lineWidth = 1;
+    dmp->i->dm_light = 1;
+    dmp->i->dm_bytes_per_pixel = sizeof(GLuint);
+    dmp->i->dm_bits_per_channel = 8;
+    bu_vls_init(&(dmp->i->dm_log));
 
     BU_ALLOC(dmp->i->dm_vars.pub_vars, struct dm_tkvars);
-    struct dm_tkvars *pubvars = (struct dm_tkvars *)dmp->i->dm_vars.pub_vars;
+    if (dmp->i->dm_vars.pub_vars == (void *)NULL) {
+       bu_free(dmp, "tk_open: dmp");
+       return DM_NULL;
+    }
+    pubvars = (struct dm_tkvars *)dmp->i->dm_vars.pub_vars;
+
     BU_ALLOC(dmp->i->dm_vars.priv_vars, struct tk_vars);
-    struct tk_vars *privars = (struct tk_vars *)dmp->i->dm_vars.priv_vars;
+    if (dmp->i->dm_vars.priv_vars == (void *)NULL) {
+       bu_free(dmp->i->dm_vars.pub_vars, "tk_open: dmp->i->dm_vars.pub_vars");
+       bu_free(dmp, "tk_open: dmp");
+       return DM_NULL;
+    }
+    privvars = (struct tk_vars *)dmp->i->dm_vars.priv_vars;
 
+    dmp->i->dm_get_internal(dmp);
+    mvars = (struct modifiable_tk_vars *)dmp->i->m_vars;
+
+    dmp->i->dm_vp = &default_viewscale;
+
     bu_vls_init(&dmp->i->dm_pathName);
     bu_vls_init(&dmp->i->dm_tkName);
     bu_vls_init(&dmp->i->dm_dName);
@@ -119,16 +768,13 @@
 
     dm_processOptions(dmp, &init_proc_vls, --argc, ++argv);
 
-    if (bu_vls_strlen(&dmp->i->dm_pathName) == 0) {
+    if (bu_vls_strlen(&dmp->i->dm_pathName) == 0)
        bu_vls_printf(&dmp->i->dm_pathName, ".dm_tk%d", count);
-    }
-
     ++count;
     if (bu_vls_strlen(&dmp->i->dm_dName) == 0) {
        char *dp;
 
-       dp = DisplayString(Tk_Display(tkwin));
-
+       dp = getenv("DISPLAY");
        if (dp)
            bu_vls_strcpy(&dmp->i->dm_dName, dp);
        else
@@ -141,12 +787,72 @@
     pubvars->devbuttonrelease = LASTEvent;
     dmp->i->dm_aspect = 1.0;
 
-    privars->tkfontset = 0;
+    /* initialize modifiable variables */
+    mvars->rgb = 1;
+    mvars->doublebuffer = 1;
+    mvars->fastfog = 1;
+    mvars->fogdensity = 1.0;
+    mvars->lighting_on = dmp->i->dm_light;
+    mvars->zbuffer_on = dmp->i->dm_zbuffer;
+    mvars->zclipping_on = dmp->i->dm_zclip;
+    mvars->debug = dmp->i->dm_debugLevel;
+    mvars->bound = dmp->i->dm_bound;
+    mvars->boundFlag = dmp->i->dm_boundFlag;
 
+    /* this is important so that tk_configureWin knows to set the font */
+    pubvars->fontstruct = NULL;
+
+    if ((tmp_dpy = XOpenDisplay(bu_vls_addr(&dmp->i->dm_dName))) == NULL) {
+       bu_vls_free(&init_proc_vls);
+       (void)tk_close(dmp);
+       return DM_NULL;
+    }
+
+#ifdef HAVE_XQUERYEXTENSION
+    {
+       int return_val;
+
+       if (!XQueryExtension(tmp_dpy, "GLX", &return_val, &return_val, 
&return_val)) {
+           bu_vls_free(&init_proc_vls);
+           (void)tk_close(dmp);
+           return DM_NULL;
+       }
+    }
+#endif
+
+    screen_number = XDefaultScreen(tmp_dpy);
+    if (screen_number < 0)
+       bu_log("WARNING: screen number is [%d]\n", screen_number);
+
+    if (dmp->i->dm_width == 0) {
+       dmp->i->dm_width = XDisplayWidth(tmp_dpy, screen_number) - 30;
+       ++make_square;
+    }
+    if (dmp->i->dm_height == 0) {
+       dmp->i->dm_height = XDisplayHeight(tmp_dpy, screen_number) - 30;
+       ++make_square;
+    }
+
+    if (make_square > 0) {
+       /* Make window square */
+       if (dmp->i->dm_height <
+           dmp->i->dm_width)
+           dmp->i->dm_width =
+               dmp->i->dm_height;
+       else
+           dmp->i->dm_height =
+               dmp->i->dm_width;
+    }
+
+    XCloseDisplay(tmp_dpy);
+
     if (dmp->i->dm_top) {
        /* Make xtkwin a toplevel window */
-       pubvars->xtkwin = Tk_CreateWindowFromPath(interp,
-               tkwin, bu_vls_addr(&dmp->i->dm_pathName), 
bu_vls_addr(&dmp->i->dm_dName));
+       pubvars->xtkwin =
+           Tk_CreateWindowFromPath(interp,
+                                   tkwin,
+                                   bu_vls_addr(&dmp->i->dm_pathName),
+                                   bu_vls_addr(&dmp->i->dm_dName));
        pubvars->top = pubvars->xtkwin;
     } else {
        char *cp;
@@ -159,7 +865,8 @@
 
            bu_vls_strncpy(&top_vls, (const char 
*)bu_vls_addr(&dmp->i->dm_pathName), cp - bu_vls_addr(&dmp->i->dm_pathName));
 
-           pubvars->top = Tk_NameToWindow(interp, bu_vls_addr(&top_vls), 
tkwin);
+           pubvars->top =
+               Tk_NameToWindow(interp, bu_vls_addr(&top_vls), tkwin);
            bu_vls_free(&top_vls);
        }
 
@@ -170,7 +877,8 @@
     }
 
     if (pubvars->xtkwin == NULL) {
-       bu_log("tk_open: Failed to open %s\n", 
bu_vls_addr(&dmp->i->dm_pathName));
+       bu_log("dm-tk: Failed to open %s\n", bu_vls_addr(&dmp->i->dm_pathName));
+       bu_vls_free(&init_proc_vls);
        (void)tk_close(dmp);
        return DM_NULL;
     }
@@ -178,10 +886,13 @@
     bu_vls_printf(&dmp->i->dm_tkName, "%s",
                  (char *)Tk_Name(pubvars->xtkwin));
 
+    Tk_SetWindowBackground(pubvars->xtkwin, 
BlackPixelOfScreen(Tk_Screen(pubvars->xtkwin)));
+
     if (bu_vls_strlen(&init_proc_vls) > 0) {
        bu_vls_printf(&str, "%s %s\n", bu_vls_addr(&init_proc_vls), 
bu_vls_addr(&dmp->i->dm_pathName));
 
        if (Tcl_Eval(interp, bu_vls_addr(&str)) == BRLCAD_ERROR) {
+           bu_vls_free(&init_proc_vls);
            bu_vls_free(&str);
            (void)tk_close(dmp);
            return DM_NULL;
@@ -191,476 +902,1096 @@
     bu_vls_free(&init_proc_vls);
     bu_vls_free(&str);
 
-    pubvars->dpy = Tk_Display(pubvars->top);
-    dpy = pubvars->dpy;
+    pubvars->dpy =
+       Tk_Display(pubvars->top);
 
     /* make sure there really is a display before proceeding. */
-    if (!dpy) {
+    if (!(pubvars->dpy)) {
+       bu_vls_free(&init_proc_vls);
+       bu_vls_free(&str);
        (void)tk_close(dmp);
        return DM_NULL;
     }
 
-    if (dmp->i->dm_width == 0) {
-       dmp->i->dm_width =
-           WidthOfScreen(Tk_Screen(pubvars->xtkwin)) - 30;
-       ++make_square;
-    }
+    Tk_GeometryRequest(pubvars->xtkwin,
+                      dmp->i->dm_width,
+                      dmp->i->dm_height);
 
-    if (dmp->i->dm_height == 0) {
-       dmp->i->dm_height = HeightOfScreen(Tk_Screen(pubvars->xtkwin)) - 30;
-       ++make_square;
+    /* must do this before MakeExist */
+    if ((pubvars->vip=tk_choose_visual(dmp, pubvars->xtkwin)) == NULL) {
+       bu_log("tk_open: Can't get an appropriate visual.\n");
+       (void)tk_close(dmp);
+       return DM_NULL;
     }
 
-    if (make_square > 0) {
-       /* Make window square */
-       if (dmp->i->dm_height <
-           dmp->i->dm_width)
-           dmp->i->dm_width = dmp->i->dm_height;
-       else
-           dmp->i->dm_height = dmp->i->dm_width;
-    }
+    pubvars->depth = mvars->depth;
 
-    Tk_GeometryRequest(pubvars->xtkwin,
-                      dmp->i->dm_width,
-                      dmp->i->dm_height);
+    Tk_MakeWindowExist(pubvars->xtkwin);
 
-    Tk_MakeWindowExist(pubvars->xtkwin);
     pubvars->win = Tk_WindowId(pubvars->xtkwin);
     dmp->i->dm_id = pubvars->win;
 
-    privars->pix =
-       Tk_GetPixmap(pubvars->dpy,
-                    DefaultRootWindow(pubvars->dpy),
-                    dmp->i->dm_width,
-                    dmp->i->dm_height,
-                    Tk_Depth(pubvars->xtkwin));
+    /* open GLX context */
+    if ((privvars->glxc =
+        glXCreateContext(pubvars->dpy, pubvars->vip, (GLXContext)NULL, 
GL_TRUE))==NULL) {
+       bu_log("tk_open: couldn't create glXContext.\n");
+       (void)tk_close(dmp);
+       return DM_NULL;
+    }
 
-    fg.red = 65535;
-    fg.green = fg.blue = 0;
+    /* If we used an indirect context, then as far as sgi is concerned,
+     * gl hasn't been used.
+     */
+    privvars->is_direct = (char) glXIsDirect(pubvars->dpy, privvars->glxc);
 
-    privars->fg = Tk_GetColorByValue(pubvars->xtkwin, &fg)->pixel;
+#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
+    /*
+     * Take a look at the available input devices. We're looking
+     * for "dial+buttons".
+     */
+    if (XQueryExtension(pubvars->dpy, "XInputExtension", &unused, &unused, 
&unused)) {
+       olist = list = (XDeviceInfoPtr)XListInputDevices(pubvars->dpy, 
&ndevices);
+    }
 
-    bg.red = bg.green = bg.blue = 3277;
+    if (list == (XDeviceInfoPtr)NULL ||
+       list == (XDeviceInfoPtr)1) goto Done;
 
-    privars->bg = Tk_GetColorByValue(pubvars->xtkwin, &bg)->pixel;
+    for (j = 0; j < ndevices; ++j, list++) {
+       if (list->use == IsXExtensionDevice) {
+           if (BU_STR_EQUAL(list->name, "dial+buttons")) {
+               if ((dev = XOpenDevice(pubvars->dpy,
+                                      list->id)) == (XDevice *)NULL) {
+                   bu_log("tk_open: Couldn't open the dials+buttons\n");
+                   goto Done;
+               }
 
-    gcv.background = privars->bg;
-    gcv.foreground = privars->fg;
+               for (cip = dev->classes, k = 0; k < dev->num_classes;
+                    ++k, ++cip) {
+                   switch (cip->input_class) {
+#ifdef IR_BUTTONS
+                       case ButtonClass:
+                           DeviceButtonPress(dev, pubvars->devbuttonpress,
+                                             e_class[nclass]);
+                           ++nclass;
+                           DeviceButtonRelease(dev, pubvars->devbuttonrelease,
+                                               e_class[nclass]);
+                           ++nclass;
+                           break;
+#endif
+#ifdef IR_KNOBS
+                       case ValuatorClass:
+                           DeviceMotionNotify(dev, pubvars->devmotionnotify,
+                                              e_class[nclass]);
+                           ++nclass;
+                           break;
+#endif
+                       default:
+                           break;
+                   }
+               }
 
-    privars->gc = Tk_GetGC(pubvars->xtkwin, (GCForeground|GCBackground), &gcv);
+               XSelectExtensionEvent(pubvars->dpy, pubvars->win, e_class, 
nclass);
+               goto Done;
+           }
+       }
+    }
+Done:
+    XFreeDeviceList(olist);
 
-    (void)tk_configureWin_guts(dmp, 1);
+#endif /* HAVE_X11_EXTENSIONS_XINPUT_H */
 
-    /*
-      Tk_SetWindowBackground(pubvars->xtkwin,
-      privars->bg);
-    */
     Tk_MapWindow(pubvars->xtkwin);
 
-    MAT_IDN(privars->mod_mat);
-    MAT_IDN(privars->disp_mat);
+    if (!glXMakeCurrent(pubvars->dpy, pubvars->win, privvars->glxc)) {
+       bu_log("tk_open: Couldn't make context current\n");
+       (void)tk_close(dmp);
+       return DM_NULL;
+    }
 
-    privars->xmat = &(privars->mod_mat[0]);
+    /* display list (fontOffset + char) will display a given ASCII char */
+    if ((privvars->fontOffset = glGenLists(128))==0) {
+       bu_log("dm-tk: Can't make display lists for font.\n");
+       (void)tk_close(dmp);
+       return DM_NULL;
+    }
 
+    /* This is the applications display list offset */
+    dmp->i->dm_displaylist = privvars->fontOffset + 128;
+
+    tk_setBGColor(dmp, 0, 0, 0);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+    if (mvars->doublebuffer)
+       glDrawBuffer(GL_BACK);
+    else
+       glDrawBuffer(GL_FRONT);
+
+    /* do viewport, ortho commands and initialize font */
+    (void)tk_configureWin_guts(dmp, 1);
+
+    /* Lines will be solid when stippling disabled, dashed when enabled*/
+    glLineStipple(1, 0xCF33);
+    glDisable(GL_LINE_STIPPLE);
+
+    backgnd[0] = backgnd[1] = backgnd[2] = backgnd[3] = 0.0;
+    glFogi(GL_FOG_MODE, GL_LINEAR);
+    glFogf(GL_FOG_START, 0.0);
+    glFogf(GL_FOG_END, 2.0);
+    glFogfv(GL_FOG_COLOR, backgnd);
+
+    /*XXX Need to do something about VIEWFACTOR */
+    glFogf(GL_FOG_DENSITY, VIEWFACTOR);
+
+    /* Initialize matrices */
+    /* Leave it in model_view mode normally */
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    glOrtho(-xlim_view, xlim_view, -ylim_view, ylim_view, 0.0, 2.0);
+    glGetDoublev(GL_PROJECTION_MATRIX, privvars->faceplate_mat);
+    glPushMatrix();
+    glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity();
+    glPushMatrix();
+    glLoadIdentity();
+    privvars->face_flag = 1;   /* faceplate matrix is on top of stack */
+
+    tk_setZBuffer(dmp, dmp->i->dm_zbuffer);
+    tk_setLight(dmp, dmp->i->dm_light);
+
     return dmp;
 }
 
 
-
-/**
- * @proc tk_close
- *
- * Gracefully release the display.
- */
-HIDDEN int
-tk_close(struct dm *dmp)
+int
+tk_share_dlist(struct dm *dmp1, struct dm *dmp2)
 {
-    struct dm_tkvars *pubvars = (struct dm_tkvars *)dmp->i->dm_vars.pub_vars;
-    struct tk_vars *privars = (struct tk_vars *)dmp->i->dm_vars.priv_vars;
+    struct modifiable_tk_vars *mvars = (struct modifiable_tk_vars 
*)dmp1->i->m_vars;
+    struct tk_vars *privars = (struct tk_vars *)dmp1->i->dm_vars.priv_vars;
+    GLfloat backgnd[4];
+    GLfloat vf;
+    GLXContext old_glxContext;
 
-    if (pubvars->dpy) {
-       if (privars->gc)
-           Tk_FreeGC(pubvars->dpy, privars->gc);
+    if (dmp1 == (struct dm *)NULL)
+       return BRLCAD_ERROR;
 
-       if (privars->pix)
-           Tk_FreePixmap(pubvars->dpy, privars->pix);
+    if (dmp2 == (struct dm *)NULL) {
+       /* create a new graphics context for dmp1 with private display lists */
 
-       /*XXX Possibly need to free the colormap */
-       if (pubvars->cmap)
-           Tk_FreeColormap(pubvars->dpy, pubvars->cmap);
+       old_glxContext = privars->glxc;
 
-       if (pubvars->xtkwin)
-           Tk_DestroyWindow(pubvars->xtkwin);
+       if ((privars->glxc =
+            glXCreateContext(((struct dm_tkvars 
*)dmp1->i->dm_vars.pub_vars)->dpy,
+                             ((struct dm_tkvars 
*)dmp1->i->dm_vars.pub_vars)->vip,
+                             (GLXContext)NULL, GL_TRUE))==NULL) {
+           bu_log("tk_share_dlist: couldn't create glXContext.\nUsing old 
context\n.");
+           privars->glxc = old_glxContext;
 
+           return BRLCAD_ERROR;
+       }
+
+       if (!glXMakeCurrent(((struct dm_tkvars 
*)dmp1->i->dm_vars.pub_vars)->dpy,
+                           ((struct dm_tkvars 
*)dmp1->i->dm_vars.pub_vars)->win,
+                           privars->glxc)) {
+           bu_log("tk_share_dlist: Couldn't make context current\nUsing old 
context\n.");
+           privars->glxc = old_glxContext;
+
+           return BRLCAD_ERROR;
+       }
+
+       /* display list (fontOffset + char) will display a given ASCII char */
+       if ((privars->fontOffset = glGenLists(128))==0) {
+           bu_log("dm-tk: Can't make display lists for font.\nUsing old 
context\n.");
+           privars->glxc = old_glxContext;
+
+           return BRLCAD_ERROR;
+       }
+
+       /* This is the applications display list offset */
+       dmp1->i->dm_displaylist = privars->fontOffset + 128;
+
+       tk_setBGColor(dmp1, 0, 0, 0);
+       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+       if (mvars->doublebuffer)
+           glDrawBuffer(GL_BACK);
+       else
+           glDrawBuffer(GL_FRONT);
+
+       /* this is important so that tk_configureWin knows to set the font */
+       ((struct dm_tkvars *)dmp1->i->dm_vars.pub_vars)->fontstruct = NULL;
+
+       /* do viewport, ortho commands and initialize font */
+       (void)tk_configureWin_guts(dmp1, 1);
+
+       /* Lines will be solid when stippling disabled, dashed when enabled*/
+       glLineStipple(1, 0xCF33);
+       glDisable(GL_LINE_STIPPLE);
+
+       backgnd[0] = backgnd[1] = backgnd[2] = backgnd[3] = 0.0;
+       glFogi(GL_FOG_MODE, GL_LINEAR);
+       glFogf(GL_FOG_START, 0.0);
+       glFogf(GL_FOG_END, 2.0);
+       glFogfv(GL_FOG_COLOR, backgnd);
+
+       /*XXX Need to do something about VIEWFACTOR */
+       vf = 1.0/(*dmp1->i->dm_vp);
+       glFogf(GL_FOG_DENSITY, vf);
+
+       /* Initialize matrices */
+       /* Leave it in model_view mode normally */
+       glMatrixMode(GL_PROJECTION);
+       glLoadIdentity();
+       glOrtho(-xlim_view, xlim_view, -ylim_view, ylim_view, 0.0, 2.0);
+       glGetDoublev(GL_PROJECTION_MATRIX, privars->faceplate_mat);
+       glPushMatrix();
+       glMatrixMode(GL_MODELVIEW);
+       glLoadIdentity();
+       glPushMatrix();
+       glLoadIdentity();
+       privars->face_flag = 1; /* faceplate matrix is on top of stack */
+
+       /* destroy old context */
+       glXMakeCurrent(((struct dm_tkvars *)dmp1->i->dm_vars.pub_vars)->dpy, 
None, NULL);
+       glXDestroyContext(((struct dm_tkvars *)dmp1->i->dm_vars.pub_vars)->dpy, 
old_glxContext);
+    } else {
+       /* dmp1 will share its display lists with dmp2 */
+
+       if (!BU_STR_EQUAL(dmp1->i->dm_name, dmp2->i->dm_name)) {
+           return BRLCAD_ERROR;
+       }
+       if (bu_vls_strcmp(&dmp1->i->dm_dName, &dmp2->i->dm_dName)) {
+           return BRLCAD_ERROR;
+       }
+
+       old_glxContext = ((struct tk_vars *)dmp2->i->dm_vars.priv_vars)->glxc;
+
+       if ((((struct tk_vars *)dmp2->i->dm_vars.priv_vars)->glxc =
+            glXCreateContext(((struct dm_tkvars 
*)dmp2->i->dm_vars.pub_vars)->dpy,
+                             ((struct dm_tkvars 
*)dmp2->i->dm_vars.pub_vars)->vip,
+                             privars->glxc,
+                             GL_TRUE))==NULL) {
+           bu_log("tk_share_dlist: couldn't create glXContext.\nUsing old 
context\n.");
+           ((struct tk_vars *)dmp2->i->dm_vars.priv_vars)->glxc = 
old_glxContext;
+
+           return BRLCAD_ERROR;
+       }
+
+       if (!glXMakeCurrent(((struct dm_tkvars 
*)dmp2->i->dm_vars.pub_vars)->dpy,
+                           ((struct dm_tkvars 
*)dmp2->i->dm_vars.pub_vars)->win,
+                           ((struct tk_vars 
*)dmp2->i->dm_vars.priv_vars)->glxc)) {
+           bu_log("tk_share_dlist: Couldn't make context current\nUsing old 
context\n.");
+           ((struct tk_vars *)dmp2->i->dm_vars.priv_vars)->glxc = 
old_glxContext;
+
+           return BRLCAD_ERROR;
+       }
+
+       ((struct tk_vars *)dmp2->i->dm_vars.priv_vars)->fontOffset = 
privars->fontOffset;
+       dmp2->i->dm_displaylist = dmp1->i->dm_displaylist;
+
+       tk_setBGColor(dmp2, 0, 0, 0);
+       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+       if (mvars->doublebuffer)
+           glDrawBuffer(GL_BACK);
+       else
+           glDrawBuffer(GL_FRONT);
+
+       /* do viewport, ortho commands and initialize font */
+       (void)tk_configureWin_guts(dmp2, 1);
+
+       /* Lines will be solid when stippling disabled, dashed when enabled*/
+       glLineStipple(1, 0xCF33);
+       glDisable(GL_LINE_STIPPLE);
+
+       backgnd[0] = backgnd[1] = backgnd[2] = backgnd[3] = 0.0;
+       glFogi(GL_FOG_MODE, GL_LINEAR);
+       glFogf(GL_FOG_START, 0.0);
+       glFogf(GL_FOG_END, 2.0);
+       glFogfv(GL_FOG_COLOR, backgnd);
+
+       /*XXX Need to do something about VIEWFACTOR */
+       vf = 1.0/(*dmp2->i->dm_vp);
+       glFogf(GL_FOG_DENSITY, vf);
+
+       /* Initialize matrices */
+       /* Leave it in model_view mode normally */
+       glMatrixMode(GL_PROJECTION);
+       glLoadIdentity();
+       glOrtho(-xlim_view, xlim_view, -ylim_view, ylim_view, 0.0, 2.0);
+       glGetDoublev(GL_PROJECTION_MATRIX, ((struct tk_vars 
*)dmp2->i->dm_vars.priv_vars)->faceplate_mat);
+       glPushMatrix();
+       glMatrixMode(GL_MODELVIEW);
+       glLoadIdentity();
+       glPushMatrix();
+       glLoadIdentity();
+       ((struct tk_vars *)dmp2->i->dm_vars.priv_vars)->face_flag = 1; /* 
faceplate matrix is on top of stack */
+
+       /* destroy old context */
+       glXMakeCurrent(((struct dm_tkvars *)dmp2->i->dm_vars.pub_vars)->dpy, 
None, NULL);
+       glXDestroyContext(((struct dm_tkvars *)dmp2->i->dm_vars.pub_vars)->dpy, 
old_glxContext);
     }
 
-    bu_vls_free(&dmp->i->dm_pathName);
-    bu_vls_free(&dmp->i->dm_tkName);
-    bu_vls_free(&dmp->i->dm_dName);
-    bu_free(dmp->i->dm_vars.priv_vars, "tk_close: tk_vars");
-    bu_free(dmp->i->dm_vars.pub_vars, "tk_close: dm_tkvars");
-    bu_free(dmp->i, "tk_close: dmp->i");
-    bu_free(dmp, "tk_close: dmp");
-
     return BRLCAD_OK;
 }
 
-int
-tk_viable(const char *UNUSED(dpy_string))
-{
-    return 1;
-}
 
-/**
- * @proc tk_drawBegin
- * This white-washes the dm's pixmap with the background color.
+/*
+ * There are global variables which are parameters to this routine.
  */
 HIDDEN int
 tk_drawBegin(struct dm *dmp)
 {
     struct dm_tkvars *pubvars = (struct dm_tkvars *)dmp->i->dm_vars.pub_vars;
+    struct modifiable_tk_vars *mvars = (struct modifiable_tk_vars 
*)dmp->i->m_vars;
     struct tk_vars *privars = (struct tk_vars *)dmp->i->dm_vars.priv_vars;
 
-    XGCValues gcv;
+    GLfloat fogdepth;
 
-    if (dmp->i->dm_debugLevel)
-       bu_log("tk_drawBegin()\n");
+    if (dmp->i->dm_debugLevel) {
+       bu_log("tk_drawBegin\n");
+    }
 
-    /* clear pixmap */
-    gcv.foreground = privars->bg;
-    XChangeGC(pubvars->dpy,
-             privars->gc,
-             GCForeground, &gcv);
-    XFillRectangle(pubvars->dpy,
-                  privars->pix,
-                  privars->gc, 0,
-                  0, dmp->i->dm_width + 1,
-                  dmp->i->dm_height + 1);
+    if (dmp->i->dm_debugLevel == 3) {
+       GLfloat m[16];
+       struct bu_vls tmp_vls = BU_VLS_INIT_ZERO;
 
-    /* reset foreground */
+       bu_vls_printf(&tmp_vls, "initial view matrix = \n");
 
-    gcv.foreground = privars->fg;
-    XChangeGC(pubvars->dpy, privars->gc, GCForeground, &gcv);
+       glGetFloatv (GL_MODELVIEW_MATRIX, m);
+       tk_printglmat(&tmp_vls, m);
+       bu_vls_printf(&tmp_vls, "initial projection matrix = \n");
+       glGetFloatv (GL_PROJECTION_MATRIX, m);
+       tk_printglmat(&tmp_vls, m);
 
+       bu_log("%s", bu_vls_addr(&tmp_vls));
+       bu_vls_free(&tmp_vls);
+    }
+
+
+
+    if (!glXMakeCurrent(pubvars->dpy,
+                       pubvars->win,
+                       privars->glxc)) {
+       bu_log("tk_drawBegin: Couldn't make context current\n");
+       return BRLCAD_ERROR;
+    }
+
+    /* clear back buffer */
+    if (!dmp->i->dm_clearBufferAfter && mvars->doublebuffer) {
+       glClearColor(privars->r,
+                    privars->g,
+                    privars->b,
+                    0.0);
+       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+    }
+
+    if (privars->face_flag) {
+       glMatrixMode(GL_PROJECTION);
+       glPopMatrix();
+       glMatrixMode(GL_MODELVIEW);
+       glPopMatrix();
+       privars->face_flag = 0;
+       if (mvars->cueing_on) {
+           glEnable(GL_FOG);
+           /*XXX Need to do something with Viewscale */
+           fogdepth = 2.2 * (*dmp->i->dm_vp); /* 2.2 is heuristic */
+           glFogf(GL_FOG_END, fogdepth);
+           fogdepth = (GLfloat) (0.5*mvars->fogdensity/
+                                 (*dmp->i->dm_vp));
+           glFogf(GL_FOG_DENSITY, fogdepth);
+           glFogi(GL_FOG_MODE, dmp->i->dm_perspective ? GL_EXP : GL_LINEAR);
+       }
+       if (dmp->i->dm_light) {
+           glEnable(GL_LIGHTING);
+       }
+    }
+
+    if (dmp->i->dm_debugLevel == 3) {
+       GLfloat m[16];
+       struct bu_vls tmp_vls = BU_VLS_INIT_ZERO;
+
+       bu_vls_printf(&tmp_vls, "after begin view matrix = \n");
+
+       glGetFloatv (GL_MODELVIEW_MATRIX, m);
+       tk_printglmat(&tmp_vls, m);
+       bu_vls_printf(&tmp_vls, "after begin projection matrix = \n");
+       glGetFloatv (GL_PROJECTION_MATRIX, m);
+       tk_printglmat(&tmp_vls, m);
+
+       bu_log("%s", bu_vls_addr(&tmp_vls));
+       bu_vls_free(&tmp_vls);
+    }
+
+
     return BRLCAD_OK;
 }
 
 
-/**
- * tk_drawEnd
- * This copies the pixmap into the window.
- */
 HIDDEN int
 tk_drawEnd(struct dm *dmp)
 {
     struct dm_tkvars *pubvars = (struct dm_tkvars *)dmp->i->dm_vars.pub_vars;
+    struct modifiable_tk_vars *mvars = (struct modifiable_tk_vars 
*)dmp->i->m_vars;
     struct tk_vars *privars = (struct tk_vars *)dmp->i->dm_vars.priv_vars;
 
     if (dmp->i->dm_debugLevel)
-       bu_log("tk_drawEnd()\n");
+       bu_log("tk_drawEnd\n");
 
-    XCopyArea(pubvars->dpy,
-             privars->pix,
-             pubvars->win,
-             privars->gc,
-             0, 0, dmp->i->dm_width,
-             dmp->i->dm_height, 0, 0);
+    if (dmp->i->dm_debugLevel == 3) {
+       GLfloat m[16];
+       struct bu_vls tmp_vls = BU_VLS_INIT_ZERO;
+       bu_vls_printf(&tmp_vls, "beginning of end view matrix = \n");
+       glGetFloatv (GL_MODELVIEW_MATRIX, m);
+       tk_printglmat(&tmp_vls, m);
+       bu_vls_printf(&tmp_vls, "beginning of end projection matrix = \n");
+       glGetFloatv (GL_PROJECTION_MATRIX, m);
+       tk_printglmat(&tmp_vls, m);
+       bu_log("%s", bu_vls_addr(&tmp_vls));
+       bu_vls_free(&tmp_vls);
+    }
 
 
-    /* Prevent lag between events and updates */
-    XSync(((struct dm_tkvars *)dmp->i->dm_vars.pub_vars)->dpy, 0);
+    if (dmp->i->dm_light) {
+       glMatrixMode(GL_MODELVIEW);
+       glLoadIdentity();
+       glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
+    }
 
+    if (mvars->doublebuffer) {
+       glXSwapBuffers(pubvars->dpy,
+                      pubvars->win);
+
+       if (dmp->i->dm_clearBufferAfter) {
+           /* give Graphics pipe time to work */
+           glClearColor(privars->r,
+                        privars->g,
+                        privars->b,
+                        0.0);
+           glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+       }
+    }
+
+    if (dmp->i->dm_debugLevel) {
+       int error;
+       struct bu_vls tmp_vls = BU_VLS_INIT_ZERO;
+
+       bu_vls_printf(&tmp_vls, "ANY ERRORS?\n");
+
+       while ((error = glGetError())!=0) {
+           bu_vls_printf(&tmp_vls, "Error: %x\n", error);
+       }
+
+       bu_log("%s", bu_vls_addr(&tmp_vls));
+       bu_vls_free(&tmp_vls);
+    }
+
+    if (dmp->i->dm_debugLevel == 3) {
+       GLfloat m[16];
+       struct bu_vls tmp_vls = BU_VLS_INIT_ZERO;
+       bu_vls_printf(&tmp_vls, "end of drawend view matrix = \n");
+       glGetFloatv (GL_MODELVIEW_MATRIX, m);
+       tk_printglmat(&tmp_vls, m);
+       bu_vls_printf(&tmp_vls, "end of drawend projection matrix = \n");
+       glGetFloatv (GL_PROJECTION_MATRIX, m);
+       tk_printglmat(&tmp_vls, m);
+       bu_log("%s", bu_vls_addr(&tmp_vls));
+       bu_vls_free(&tmp_vls);
+    }
+
+
     return BRLCAD_OK;
 }
 
 
-/**
- * @proc tk_loadMatrix
- *
+/*
  * Load a new transformation matrix.  This will be followed by
- * many calls to tk_drawVList().
+ * many calls to tk_draw().
  */
-/* ARGSUSED */
 HIDDEN int
 tk_loadMatrix(struct dm *dmp, fastf_t *mat, int which_eye)
 {
-    struct tk_vars *privars = (struct tk_vars *)dmp->i->dm_vars.priv_vars;
+    fastf_t *mptr;
+    GLfloat gtmat[16];
 
-    if (dmp->i->dm_debugLevel) {
+    if (dmp->i->dm_debugLevel == 1)
        bu_log("tk_loadMatrix()\n");
 
-       bu_log("which eye = %d\t", which_eye);
-       bu_log("transformation matrix = \n");
+    if (dmp->i->dm_debugLevel == 3) {
+       GLfloat m[16];
+       struct bu_vls tmp_vls = BU_VLS_INIT_ZERO;
+       bu_vls_printf(&tmp_vls, "beginning of loadMatrix view matrix = \n");
+       glGetFloatv (GL_MODELVIEW_MATRIX, m);
+       tk_printglmat(&tmp_vls, m);
+       bu_vls_printf(&tmp_vls, "beginning of loadMatrix projection matrix = 
\n");
+       glGetFloatv (GL_PROJECTION_MATRIX, m);
+       tk_printglmat(&tmp_vls, m);
+       bu_log("%s", bu_vls_addr(&tmp_vls));
+       bu_vls_free(&tmp_vls);
+    }
 
-       bu_log("%g %g %g %g\n", mat[0], mat[1], mat[2], mat[3]);
-       bu_log("%g %g %g %g\n", mat[4], mat[5], mat[6], mat[7]);
-       bu_log("%g %g %g %g\n", mat[8], mat[9], mat[10], mat[11]);
-       bu_log("%g %g %g %g\n", mat[12], mat[13], mat[14], mat[15]);
+
+    if (dmp->i->dm_debugLevel == 3) {
+       struct bu_vls tmp_vls = BU_VLS_INIT_ZERO;
+
+       bu_vls_printf(&tmp_vls, "transformation matrix = \n");
+       tk_printmat(&tmp_vls, mat);
+
+       bu_log("%s", bu_vls_addr(&tmp_vls));
+       bu_vls_free(&tmp_vls);
     }
 
-    MAT_COPY(privars->mod_mat, mat);
+    switch (which_eye) {
+       case 0:
+           /* Non-stereo */
+           break;
+       case 1:
+           /* R eye */
+           glViewport(0,  0, (XMAXSCREEN)+1, (YSTEREO)+1);
+           glScissor(0,  0, (XMAXSCREEN)+1, (YSTEREO)+1);
+           tk_drawString2D(dmp, "R", 0.986, 0.0, 0, 1);
+           break;
+       case 2:
+           /* L eye */
+           glViewport(0,  0+YOFFSET_LEFT, (XMAXSCREEN)+1,
+                      (YSTEREO+YOFFSET_LEFT)-(YOFFSET_LEFT)+1);
+           glScissor(0,  0+YOFFSET_LEFT, (XMAXSCREEN)+1,
+                     (YSTEREO+YOFFSET_LEFT)-(YOFFSET_LEFT)+1);
+           break;
+    }
+
+    mptr = mat;
+
+    gtmat[0] = *(mptr++);
+    gtmat[4] = *(mptr++);
+    gtmat[8] = *(mptr++);
+    gtmat[12] = *(mptr++);
+
+    gtmat[1] = *(mptr++) * dmp->i->dm_aspect;
+    gtmat[5] = *(mptr++) * dmp->i->dm_aspect;
+    gtmat[9] = *(mptr++) * dmp->i->dm_aspect;
+    gtmat[13] = *(mptr++) * dmp->i->dm_aspect;
+
+    gtmat[2] = *(mptr++);
+    gtmat[6] = *(mptr++);
+    gtmat[10] = *(mptr++);
+    gtmat[14] = *(mptr++);
+
+    gtmat[3] = *(mptr++);
+    gtmat[7] = *(mptr++);
+    gtmat[11] = *(mptr++);
+    gtmat[15] = *(mptr++);
+
+    glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity();
+    glLoadMatrixf(gtmat);
+
+    if (dmp->i->dm_debugLevel == 3) {
+       GLfloat m[16];
+       struct bu_vls tmp_vls = BU_VLS_INIT_ZERO;
+       bu_vls_printf(&tmp_vls, "end of loadMatrix view matrix = \n");
+       glGetFloatv (GL_MODELVIEW_MATRIX, m);
+       tk_printglmat(&tmp_vls, m);
+       bu_vls_printf(&tmp_vls, "end of loadMatrix projection matrix = \n");
+       glGetFloatv (GL_PROJECTION_MATRIX, m);
+       tk_printglmat(&tmp_vls, m);
+       bu_log("%s", bu_vls_addr(&tmp_vls));
+       bu_vls_free(&tmp_vls);
+    }
+
     return BRLCAD_OK;
 }
 
 
-/**
- * tk_drawVList
+/*
+ * Load a new projection matrix.
  *
  */
-
 HIDDEN int
-tk_drawVList(struct dm *dmp, struct bn_vlist *vp)
+tk_loadPMatrix(struct dm *dmp, fastf_t *mat)
 {
-    static vect_t spnt, lpnt, pnt;
-    struct bn_vlist *tvp;
-    XSegment segbuf[1024];             /* XDrawSegments list */
-    XSegment *segp;                    /* current segment */
-    int nseg;                  /* number of segments */
-    fastf_t delta;
-    point_t *pt_prev = NULL;
-    point_t tlate;
-    fastf_t dist_prev=1.0;
-    static int nvectors = 0;
+    fastf_t *mptr;
+    GLfloat gtmat[16];
 
-    struct dm_tkvars *pubvars = (struct dm_tkvars *)dmp->i->dm_vars.pub_vars;
     struct tk_vars *privars = (struct tk_vars *)dmp->i->dm_vars.priv_vars;
 
-    if (dmp->i->dm_debugLevel) {
+    glMatrixMode(GL_PROJECTION);
+
+    if (mat == (fastf_t *)NULL) {
+       if (privars->face_flag) {
+           glPopMatrix();
+           glLoadIdentity();
+           glOrtho(-xlim_view, xlim_view, -ylim_view, ylim_view, 
dmp->i->dm_clipmin[2], dmp->i->dm_clipmax[2]);
+           glPushMatrix();
+           glLoadMatrixd(privars->faceplate_mat);
+       } else {
+           glLoadIdentity();
+           glOrtho(-xlim_view, xlim_view, -ylim_view, ylim_view, 
dmp->i->dm_clipmin[2], dmp->i->dm_clipmax[2]);
+       }
+
+       return BRLCAD_OK;
+    }
+
+    mptr = mat;
+
+    gtmat[0] = *(mptr++);
+    gtmat[4] = *(mptr++);
+    gtmat[8] = *(mptr++);
+    gtmat[12] = *(mptr++);
+
+    gtmat[1] = *(mptr++);
+    gtmat[5] = *(mptr++);
+    gtmat[9] = *(mptr++);
+    gtmat[13] = *(mptr++);
+
+    gtmat[2] = *(mptr++);
+    gtmat[6] = *(mptr++);
+    gtmat[10] = -*(mptr++);
+    gtmat[14] = -*(mptr++);
+
+    gtmat[3] = *(mptr++);
+    gtmat[7] = *(mptr++);
+    gtmat[11] = *(mptr++);
+    gtmat[15] = *(mptr++);
+
+    glLoadIdentity();
+    glLoadMatrixf(gtmat);
+
+    return BRLCAD_OK;
+}
+
+
+HIDDEN int
+tk_drawVListHiddenLine(struct dm *dmp, register struct bn_vlist *vp)
+{
+    struct modifiable_tk_vars *mvars = (struct modifiable_tk_vars 
*)dmp->i->m_vars;
+    struct tk_vars *privars = (struct tk_vars *)dmp->i->dm_vars.priv_vars;
+
+    register struct bn_vlist *tvp;
+    register int first;
+
+    if (dmp->i->dm_debugLevel == 1)
        bu_log("tk_drawVList()\n");
-       bu_log("vp - %p, perspective - %d\n", (void *)vp, 
dmp->i->dm_perspective);
+
+
+    /* First, draw polygons using background color. */
+
+    if (dmp->i->dm_light) {
+       glDisable(GL_LIGHTING);
     }
 
-    /* delta is used in clipping to insure clipped endpoint is slightly
-     * in front of eye plane (perspective mode only).
-     * This value is a SWAG that seems to work OK.
-     */
-    delta = (privars->xmat)[15]*0.0001;
-    if (delta < 0.0)
-       delta = -delta;
-    if (delta < SQRT_SMALL_FASTF)
-       delta = SQRT_SMALL_FASTF;
+    glDisable(GL_BLEND);
+    glDepthMask(GL_TRUE);
+    glEnable(GL_DEPTH_TEST);
+    glDepthFunc(GL_LEQUAL);
+    glEnable(GL_POLYGON_OFFSET_FILL);
+    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+    glPolygonOffset(1.0, 1.0);
 
-    nseg = 0;
-    segp = segbuf;
+    /* Set color to background color for drawing polygons. */
+    glColor3f(privars->r,
+             privars->g,
+             privars->b);
+
+    /* Viewing region is from -1.0 to +1.0 */
+    first = 1;
     for (BU_LIST_FOR(tvp, bn_vlist, &vp->l)) {
-       int i;
-       int nused = tvp->nused;
-       int *cmd = tvp->cmd;
+       register int i;
+       register int nused = tvp->nused;
+       register int *cmd = tvp->cmd;
        point_t *pt = tvp->pt;
-       fastf_t dist;
+       for (i = 0; i < nused; i++, cmd++, pt++) {
+           GLdouble dpt[3];
+           VMOVE(dpt, *pt); /* fastf_t-to-double */
+/*
+           if (dmp->i->dm_debugLevel > 2)
+               bu_log(" %d (%g %g %g)\n", *cmd, V3ARGS(dpt));*/
 
-       /* Viewing region is from -1.0 to +1.0 */
-       /* 2^31 ~= 2e9 -- dynamic range of a long int */
-       /* 2^(31-11) = 2^20 ~= 1e6 */
-       /* Integerize and let the X server do the clipping */
-       for (i = 0; i < nused; i++, cmd++, pt++) {
            switch (*cmd) {
+               case BN_VLIST_LINE_MOVE:
+               case BN_VLIST_LINE_DRAW:
+                   break;
                case BN_VLIST_POLY_START:
+                   /* Start poly marker & normal */
+                   if (first == 0)
+                       glEnd();
+                   first = 0;
+
+                   glBegin(GL_POLYGON);
+                   /* Set surface normal (vl_pnt points outward) */
+                   glNormal3dv(dpt);
+                   break;
+               case BN_VLIST_POLY_MOVE:
+               case BN_VLIST_POLY_DRAW:
+               case BN_VLIST_TRI_MOVE:
+               case BN_VLIST_TRI_DRAW:
+                   glVertex3dv(dpt);
+                   break;
+               case BN_VLIST_POLY_END:
+                   /* Draw, End Polygon */
+                   glEnd();
+                   first = 1;
+                   break;
                case BN_VLIST_POLY_VERTNORM:
+               case BN_VLIST_TRI_VERTNORM:
+                   /* Set per-vertex normal.  Given before vert. */
+                   glNormal3dv(dpt);
+                   break;
                case BN_VLIST_TRI_START:
-               case BN_VLIST_TRI_VERTNORM:
-                   continue;
-               case BN_VLIST_MODEL_MAT:
-                   privars->xmat = &(privars->mod_mat[0]);
-                   continue;
-               case BN_VLIST_DISPLAY_MAT:
-                   MAT4X3PNT(tlate, privars->mod_mat, *pt);
-                   privars->disp_mat[3] = tlate[0];
-                   privars->disp_mat[7] = tlate[1];
-                   privars->disp_mat[11] = tlate[2];
-                   privars->xmat = &(privars->disp_mat[0]);
-                   continue;
-               case BN_VLIST_POLY_MOVE:
+                   if (first)
+                       glBegin(GL_TRIANGLES);
+
+                   first = 0;
+
+                   /* Set surface normal (vl_pnt points outward) */
+                   glNormal3dv(dpt);
+
+                   break;
+               case BN_VLIST_TRI_END:
+                   break;
+           }
+       }
+    }
+
+    if (first == 0)
+       glEnd();
+
+    /* Last, draw wireframe/edges. */
+
+    /* Set color to wireColor for drawing wireframe/edges */
+    glColor3f(wireColor[0], wireColor[1], wireColor[2]);
+
+    /* Viewing region is from -1.0 to +1.0 */
+    first = 1;
+    for (BU_LIST_FOR(tvp, bn_vlist, &vp->l)) {
+       register int i;
+       register int nused = tvp->nused;
+       register int *cmd = tvp->cmd;
+       point_t *pt = tvp->pt;
+
+       for (i = 0; i < nused; i++, cmd++, pt++) {
+           GLdouble dpt[3];
+           VMOVE(dpt, *pt); /* fastf_t-to-double */
+/*
+           if (dmp->i->dm_debugLevel > 2)
+               bu_log(" %d (%g %g %g)\n", *cmd, V3ARGS(dpt));*/
+
+           switch (*cmd) {
                case BN_VLIST_LINE_MOVE:
-               case BN_VLIST_TRI_MOVE:
-                   /* Move, not draw */
-                   if (dmp->i->dm_debugLevel > 2) {
-                       bu_log("before transformation:\n");
-                       bu_log("pt - %lf %lf %lf\n", V3ARGS(*pt));
-                   }
+                   /* Move, start line */
+                   if (first == 0)
+                       glEnd();
+                   first = 0;
 
-                   if (dmp->i->dm_perspective > 0) {
-                       /* cannot apply perspective transformation to
-                        * points behind eye plane!!!!
-                        */
-                       dist = VDOT(*pt, &(privars->xmat)[12]) + 
privars->xmat[15];
-                       if (dist <= 0.0) {
-                           pt_prev = pt;
-                           dist_prev = dist;
-                           continue;
-                       } else {
-                           MAT4X3PNT(lpnt, privars->xmat, *pt);
-                           dist_prev = dist;
-                           pt_prev = pt;
-                       }
-                   } else {
-                           MAT4X3PNT(lpnt, privars->xmat, *pt);
-                   }
+                   glBegin(GL_LINE_STRIP);
+                   glVertex3dv(dpt);
+                   break;
+               case BN_VLIST_POLY_START:
+               case BN_VLIST_TRI_START:
+                   /* Start poly marker & normal */
+                   if (first == 0)
+                       glEnd();
+                   first = 0;
 
-                   lpnt[0] *= 2047;
-                   lpnt[1] *= 2047 * dmp->i->dm_aspect;
-                   lpnt[2] *= 2047;
-                   continue;
+                   glBegin(GL_LINE_STRIP);
+                   break;
+               case BN_VLIST_LINE_DRAW:
+               case BN_VLIST_POLY_MOVE:
                case BN_VLIST_POLY_DRAW:
+               case BN_VLIST_TRI_MOVE:
+               case BN_VLIST_TRI_DRAW:
+                   glVertex3dv(dpt);
+                   break;
                case BN_VLIST_POLY_END:
-               case BN_VLIST_LINE_DRAW:
-               case BN_VLIST_TRI_DRAW:
                case BN_VLIST_TRI_END:
-                   /* draw */
-                   if (dmp->i->dm_debugLevel > 2) {
-                       bu_log("before transformation:\n");
-                       bu_log("pt - %lf %lf %lf\n", V3ARGS(*pt));
-                   }
+                   /* Draw, End Polygon */
+                   glVertex3dv(dpt);
+                   glEnd();
+                   first = 1;
+                   break;
+               case BN_VLIST_POLY_VERTNORM:
+               case BN_VLIST_TRI_VERTNORM:
+                   /* Set per-vertex normal.  Given before vert. */
+                   glNormal3dv(dpt);
+                   break;
+           }
+       }
+    }
 
-                   if (dmp->i->dm_perspective > 0) {
-                       /* cannot apply perspective transformation to
-                        * points behind eye plane!!!!
-                        */
-                       dist = VDOT(*pt, &(privars->xmat)[12]) + 
privars->xmat[15];
-                       if (dmp->i->dm_debugLevel > 2)
-                           bu_log("dist=%g, dist_prev=%g\n", dist, dist_prev);
-                       if (dist <= 0.0) {
-                           if (dist_prev <= 0.0) {
-                               /* nothing to plot */
-                               dist_prev = dist;
-                               pt_prev = pt;
-                               continue;
-                           } else {
-                               if (pt_prev) {
-                               fastf_t alpha;
-                               vect_t diff;
-                               point_t tmp_pt;
+    if (first == 0)
+       glEnd();
 
-                               /* clip this end */
-                               VSUB2(diff, *pt, *pt_prev);
-                               alpha = (dist_prev - delta) / (dist_prev - 
dist);
-                               VJOIN1(tmp_pt, *pt_prev, alpha, diff);
-                               MAT4X3PNT(pnt, privars->xmat, tmp_pt);
-                               }
-                           }
-                       } else {
-                           if (dist_prev <= 0.0) {
-                               if (pt_prev) {
-                               fastf_t alpha;
-                               vect_t diff;
-                               point_t tmp_pt;
+    if (dmp->i->dm_light) {
+       glEnable(GL_LIGHTING);
+    }
 
-                               /* clip other end */
-                               VSUB2(diff, *pt, *pt_prev);
-                               alpha = (-dist_prev + delta) / (dist - 
dist_prev);
-                               VJOIN1(tmp_pt, *pt_prev, alpha, diff);
-                               MAT4X3PNT(pnt, privars->xmat, tmp_pt);
-                               lpnt[0] *= 2047;
-                               lpnt[1] *= 2047 * dmp->i->dm_aspect;
-                               lpnt[2] *= 2047;
-                               MAT4X3PNT(pnt, privars->xmat, *pt);
-                               }
-                           } else {
-                               MAT4X3PNT(pnt, privars->xmat, *pt);
-                           }
-                       }
-                       dist_prev = dist;
-                   } else {
-                       MAT4X3PNT(pnt, privars->xmat, *pt);
-                   }
+    if (!mvars->zbuffer_on)
+       glDisable(GL_DEPTH_TEST);
 
-                   pnt[0] *= 2047;
-                   pnt[1] *= 2047 * dmp->i->dm_aspect;
-                   pnt[2] *= 2047;
+    if (!dmp->i->dm_depthMask)
+       glDepthMask(GL_FALSE);
 
-                   /* save pnt --- it might get changed by clip() */
-                   VMOVE(spnt, pnt);
-                   pt_prev = pt;
+    glDisable(GL_POLYGON_OFFSET_FILL);
 
-                   if (dmp->i->dm_debugLevel > 2) {
-                       bu_log("before clipping:\n");
-                       bu_log("clipmin - %lf %lf %lf\n",
-                              dmp->i->dm_clipmin[X],
-                              dmp->i->dm_clipmin[Y],
-                              dmp->i->dm_clipmin[Z]);
-                       bu_log("clipmax - %lf %lf %lf\n",
-                              dmp->i->dm_clipmax[X],
-                              dmp->i->dm_clipmax[Y],
-                              dmp->i->dm_clipmax[Z]);
-                       bu_log("pt1 - %lf %lf %lf\n", lpnt[X], lpnt[Y], 
lpnt[Z]);
-                       bu_log("pt2 - %lf %lf %lf\n", pnt[X], pnt[Y], pnt[Z]);
+    return BRLCAD_OK;
+}
+
+
+HIDDEN int
+tk_drawVList(struct dm *dmp, struct bn_vlist *vp)
+{
+    struct bn_vlist *tvp;
+    register int first;
+    register int mflag = 1;
+    static float black[4] = {0.0, 0.0, 0.0, 0.0};
+    GLfloat originalPointSize, originalLineWidth;
+    GLdouble m[16];
+    GLdouble mt[16];
+    GLdouble tlate[3];
+
+    glGetFloatv(GL_POINT_SIZE, &originalPointSize);
+    glGetFloatv(GL_LINE_WIDTH, &originalLineWidth);
+
+    if (dmp->i->dm_debugLevel == 1)
+       bu_log("tk_drawVList()\n");
+
+    /* Viewing region is from -1.0 to +1.0 */
+    first = 1;
+    for (BU_LIST_FOR(tvp, bn_vlist, &vp->l)) {
+       int i;
+       int nused = tvp->nused;
+       int *cmd = tvp->cmd;
+       point_t *pt = tvp->pt;
+       for (i = 0; i < nused; i++, cmd++, pt++) {
+           GLdouble dpt[3];
+           VMOVE(dpt, *pt);
+/*
+           if (dmp->i->dm_debugLevel > 2)
+               bu_log(" %d (%g %g %g)\n", *cmd, V3ARGS(dpt));*/
+
+           switch (*cmd) {
+               case BN_VLIST_LINE_MOVE:
+                   /* Move, start line */
+                   if (first == 0)
+                       glEnd();
+                   first = 0;
+
+                   if (dmp->i->dm_light && mflag) {
+                       mflag = 0;
+                       glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, wireColor);
+                       glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, black);
+                       glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black);
+                       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, black);
+
+                       if (dmp->i->dm_transparency)
+                           glDisable(GL_BLEND);
                    }
 
-                   if (dmp->i->dm_zclip) {
-                       if (vclip(lpnt, pnt,
-                                 dmp->i->dm_clipmin,
-                                 dmp->i->dm_clipmax) == 0) {
-                           VMOVE(lpnt, spnt);
-                           continue;
-                       }
-                   } else {
-                       /* Check to see if lpnt or pnt contain values that 
exceed
-                          the capacity of a short (segbuf is an array of 
XSegments which
-                          contain shorts). If so, do clipping now. Otherwise, 
let the
-                          X server do the clipping */
-                       if (lpnt[0] < min_short || max_short < lpnt[0] ||
-                           lpnt[1] < min_short || max_short < lpnt[1] ||
-                           pnt[0] < min_short || max_short < pnt[0] ||
-                           pnt[1] < min_short || max_short < pnt[1]) {
-                           /* if the entire line segment will not be visible 
then ignore it */
-                           if (clip(&lpnt[0], &lpnt[1], &pnt[0], &pnt[1]) == 
-1) {
-                               VMOVE(lpnt, spnt);
-                               continue;
-                           }
-                       }
+                   glBegin(GL_LINE_STRIP);
+                   glVertex3dv(dpt);
+                   break;
+               case BN_VLIST_MODEL_MAT:
+                   if (first == 0) {
+                       glEnd();
+                       first = 1;
                    }
 
-                   if (dmp->i->dm_debugLevel > 2) {
-                       bu_log("after clipping:\n");
-                       bu_log("pt1 - %lf %lf %lf\n", lpnt[X], lpnt[Y], 
lpnt[Z]);
-                       bu_log("pt2 - %lf %lf %lf\n", pnt[X], pnt[Y], pnt[Z]);
+                   glMatrixMode(GL_MODELVIEW);
+                   glPopMatrix();
+                   break;
+               case BN_VLIST_DISPLAY_MAT:
+                   glMatrixMode(GL_MODELVIEW);
+                   glGetDoublev(GL_MODELVIEW_MATRIX, m);
+
+                   MAT_TRANSPOSE(mt, m);
+                   MAT4X3PNT(tlate, mt, dpt);
+
+                   glPushMatrix();
+                   glLoadIdentity();
+                   glTranslated(tlate[0], tlate[1], tlate[2]);
+                   /* 96 dpi = 3.78 pixel/mm hardcoded */
+                   glScaled(2. * 3.78 / dmp->i->dm_width,
+                            2. * 3.78 / dmp->i->dm_height,
+                            1.);
+                   break;
+               case BN_VLIST_POLY_START:
+               case BN_VLIST_TRI_START:
+                   /* Start poly marker & normal */
+
+                   if (dmp->i->dm_light && mflag) {
+                       mflag = 0;
+                       glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, black);
+                       glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, 
ambientColor);
+                       glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, 
specularColor);
+                       glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuseColor);
+
+                       switch (dmp->i->dm_light) {
+                           case 1:
+                               break;
+                           case 2:
+                               glMaterialfv(GL_BACK, GL_DIFFUSE, diffuseColor);
+                               break;
+                           case 3:
+                               glMaterialfv(GL_BACK, GL_DIFFUSE, 
backDiffuseColorDark);
+                               break;
+                           default:
+                               glMaterialfv(GL_BACK, GL_DIFFUSE, 
backDiffuseColorLight);
+                               break;
+                       }
+
+                       if (dmp->i->dm_transparency)
+                           glEnable(GL_BLEND);
                    }
 
-                   /* convert to X window coordinates */
-                   segp->x1 = (short)GED_TO_Xx(dmp, lpnt[0]);
-                   segp->y1 = (short)GED_TO_Xy(dmp, lpnt[1]);
-                   segp->x2 = (short)GED_TO_Xx(dmp, pnt[0]);
-                   segp->y2 = (short)GED_TO_Xy(dmp, pnt[1]);
+                   if (*cmd == BN_VLIST_POLY_START) {
+                       if (first == 0)
+                           glEnd();
 
-                   nseg++;
-                   segp++;
-                   VMOVE(lpnt, spnt);
+                       glBegin(GL_POLYGON);
+                   } else if (first)
+                       glBegin(GL_TRIANGLES);
 
-                   if (nseg == 1024) {
-                       XDrawSegments(pubvars->dpy,
-                                     privars->pix,
-                                     privars->gc, segbuf, nseg);
+                   /* Set surface normal (vl_pnt points outward) */
+                   glNormal3dv(dpt);
 
-                       nseg = 0;
-                       segp = segbuf;
+                   first = 0;
+
+                   break;
+               case BN_VLIST_LINE_DRAW:
+               case BN_VLIST_POLY_MOVE:
+               case BN_VLIST_POLY_DRAW:
+               case BN_VLIST_TRI_MOVE:
+               case BN_VLIST_TRI_DRAW:
+                   glVertex3dv(dpt);
+                   break;
+               case BN_VLIST_POLY_END:
+                   /* Draw, End Polygon */
+                   glEnd();
+                   first = 1;
+                   break;
+               case BN_VLIST_TRI_END:
+                   break;
+               case BN_VLIST_POLY_VERTNORM:
+               case BN_VLIST_TRI_VERTNORM:
+                   /* Set per-vertex normal.  Given before vert. */
+                   glNormal3dv(dpt);
+                   break;
+               case BN_VLIST_POINT_DRAW:
+                   if (first == 0)
+                       glEnd();
+                   first = 0;
+#if ENABLE_POINT_SMOOTH
+                   glEnable(GL_POINT_SMOOTH);
+#endif
+                   glBegin(GL_POINTS);
+                   glVertex3dv(dpt);
+                   break;
+               case BN_VLIST_LINE_WIDTH: {
+                   GLfloat lineWidth = (GLfloat)(*pt)[0];
+                   if (lineWidth > 0.0) {
+                       glLineWidth(lineWidth);
                    }
                    break;
+               }
+               case BN_VLIST_POINT_SIZE: {
+                   GLfloat pointSize = (GLfloat)(*pt)[0];
+                   if (pointSize > 0.0) {
+                       glPointSize(pointSize);
+                   }
+                   break;
+               }
            }
        }
+    }
 
-       nvectors += nused;
-       if (nvectors >= vectorThreshold) {
-           if (dmp->i->dm_debugLevel)
-               bu_log("tk_drawVList(): handle Tcl events\n");
+    if (first == 0)
+       glEnd();
 
-           nvectors = 0;
+    if (dmp->i->dm_light && dmp->i->dm_transparency)
+       glDisable(GL_BLEND);
 
-           /* Handle events in the queue */
-           while (Tcl_DoOneEvent(TCL_ALL_EVENTS|TCL_DONT_WAIT));
-       }
+    glPointSize(originalPointSize);
+    glLineWidth(originalLineWidth);
+
+    return BRLCAD_OK;
+}
+
+int
+tk_draw_data_axes(struct dm *dmp,
+                  fastf_t sf,
+                  struct bview_data_axes_state *bndasp)
+{
+    int npoints = bndasp->num_points * 6;
+    if (npoints < 1)
+        return 0;
+
+    /* set color */
+    dm_set_fg(dmp, bndasp->color[0], bndasp->color[1], bndasp->color[2], 1, 
1.0);
+
+    if (bndasp->draw > 1) {
+        if (dmp->i->dm_light)
+            glDisable(GL_LIGHTING);
+
+        glPointSize(bndasp->size);
+        dm_draw_points_3d(dmp, bndasp->num_points, bndasp->points);
+        glPointSize(1);
+
+        if (dmp->i->dm_light)
+            glEnable(GL_LIGHTING);
+
+       return 0;
     }
 
-    if (nseg) {
-       XDrawSegments(pubvars->dpy,
-                     privars->pix,
-                     privars->gc, segbuf, nseg);
+    int i, j;
+    fastf_t halfAxesSize;               /* half the length of an axis */
+    point_t ptA, ptB;
+    point_t *points;
+    /* Save the line attributes */
+    int saveLineWidth = dmp->i->dm_lineWidth;
+    int saveLineStyle = dmp->i->dm_lineStyle;
+
+    points = (point_t *)bu_calloc(npoints, sizeof(point_t), "data axes 
points");
+    halfAxesSize = bndasp->size * 0.5 * sf;
+
+    /* set linewidth */
+    dm_set_line_attr(dmp, bndasp->line_width, 0);  /* solid lines */
+
+    for (i = 0, j = -1; i < bndasp->num_points; ++i) {
+       /* draw X axis with x/y offsets */
+       VSET(ptA, bndasp->points[i][X] - halfAxesSize, bndasp->points[i][Y], 
bndasp->points[i][Z]);
+       VSET(ptB, bndasp->points[i][X] + halfAxesSize, bndasp->points[i][Y], 
bndasp->points[i][Z]);
+       ++j;
+       VMOVE(points[j], ptA);
+       ++j;
+       VMOVE(points[j], ptB);
+
+       /* draw Y axis with x/y offsets */
+       VSET(ptA, bndasp->points[i][X], bndasp->points[i][Y] - halfAxesSize, 
bndasp->points[i][Z]);
+       VSET(ptB, bndasp->points[i][X], bndasp->points[i][Y] + halfAxesSize, 
bndasp->points[i][Z]);
+       ++j;
+       VMOVE(points[j], ptA);
+       ++j;
+       VMOVE(points[j], ptB);
+
+       /* draw Z axis with x/y offsets */
+       VSET(ptA, bndasp->points[i][X], bndasp->points[i][Y], 
bndasp->points[i][Z] - halfAxesSize);
+       VSET(ptB, bndasp->points[i][X], bndasp->points[i][Y], 
bndasp->points[i][Z] + halfAxesSize);
+       ++j;
+       VMOVE(points[j], ptA);
+       ++j;
+       VMOVE(points[j], ptB);
     }
 
-    return BRLCAD_OK;
+    dm_draw_lines_3d(dmp, npoints, points, 0);
+    bu_free((void *)points, "data axes points");
+
+    /* Restore the line attributes */
+    dm_set_line_attr(dmp, saveLineWidth, saveLineStyle);
+
+
+    return 0;
 }
 
-
-int
+HIDDEN int
 tk_draw(struct dm *dmp, struct bn_vlist *(*callback_function)(void *), void 
**data)
 {
     struct bn_vlist *vp;
@@ -687,80 +2018,114 @@
 HIDDEN int
 tk_normal(struct dm *dmp)
 {
+    struct modifiable_tk_vars *mvars = (struct modifiable_tk_vars 
*)dmp->i->m_vars;
+    struct tk_vars *privars = (struct tk_vars *)dmp->i->dm_vars.priv_vars;
+
     if (dmp->i->dm_debugLevel)
-       bu_log("tk_normal()\n");
+       bu_log("tk_normal\n");
 
+    if (dmp->i->dm_debugLevel == 3) {
+       GLfloat m[16];
+       struct bu_vls tmp_vls = BU_VLS_INIT_ZERO;
+       bu_vls_printf(&tmp_vls, "beginning of tk_normal view matrix = \n");
+       glGetFloatv (GL_MODELVIEW_MATRIX, m);
+       tk_printglmat(&tmp_vls, m);
+       bu_vls_printf(&tmp_vls, "beginning of tk_normal projection matrix = 
\n");
+       glGetFloatv (GL_PROJECTION_MATRIX, m);
+       tk_printglmat(&tmp_vls, m);
+       bu_log("%s", bu_vls_addr(&tmp_vls));
+       bu_vls_free(&tmp_vls);
+    }
+
+    if (!privars->face_flag) {
+       glMatrixMode(GL_PROJECTION);
+       glPushMatrix();
+       glLoadMatrixd(privars->faceplate_mat);
+       glMatrixMode(GL_MODELVIEW);
+       glPushMatrix();
+       glLoadIdentity();
+       privars->face_flag = 1;
+       if (mvars->cueing_on)
+           glDisable(GL_FOG);
+       if (dmp->i->dm_light)
+           glDisable(GL_LIGHTING);
+    }
+
+    if (dmp->i->dm_debugLevel == 3) {
+       GLfloat m[16];
+       struct bu_vls tmp_vls = BU_VLS_INIT_ZERO;
+       bu_vls_printf(&tmp_vls, "end of tk_normal view matrix = \n");
+       glGetFloatv (GL_MODELVIEW_MATRIX, m);
+       tk_printglmat(&tmp_vls, m);
+       bu_vls_printf(&tmp_vls, "end of tk_normal projection matrix = \n");
+       glGetFloatv (GL_PROJECTION_MATRIX, m);
+       tk_printglmat(&tmp_vls, m);
+       bu_log("%s", bu_vls_addr(&tmp_vls));
+       bu_vls_free(&tmp_vls);
+    }
+
     return BRLCAD_OK;
 }
 
 
 /*
- * Output a string into the displaylist.
+ * Output a string.
  * The starting position of the beam is as specified.
  */
-/* ARGSUSED */
 HIDDEN int
-tk_drawString2D(struct dm *dmp, const char *str, fastf_t x, fastf_t y, int 
size, int use_aspect)
+tk_drawString2D(struct dm *dmp, const char *str, fastf_t x, fastf_t y, int 
UNUSED(size), int use_aspect)
 {
-    int sx, sy;
-    struct dm_tkvars *pubvars = (struct dm_tkvars *)dmp->i->dm_vars.pub_vars;
     struct tk_vars *privars = (struct tk_vars *)dmp->i->dm_vars.priv_vars;
+    if (dmp->i->dm_debugLevel)
+       bu_log("tk_drawString2D()\n");
 
-    if (dmp->i->dm_debugLevel) {
-       bu_log("tk_drawString2D():\n");
-       bu_log("\tstr - %s\n", str);
-       bu_log("\tx - %g\n", x);
-       bu_log("\ty - %g\n", y);
-       bu_log("\tsize - %d\n", size);
+    if (use_aspect)
+       glRasterPos2f(x, y * dmp->i->dm_aspect);
+    else
+       glRasterPos2f(x, y);
 
-       bu_log("color = %lu\n", privars->fg);
-       /* bu_log("real_color = %d\n", privars->gc->foreground); */
+    glListBase(privars->fontOffset);
+    glCallLists(strlen(str), GL_UNSIGNED_BYTE,  str);
 
-       if (use_aspect) {
-           bu_log("\tuse_aspect - %d\t\taspect ratio - %g\n", use_aspect, 
dmp->i->dm_aspect);
-       } else
-           bu_log("\tuse_aspect - 0");
-    }
+    return BRLCAD_OK;
+}
 
-    sx = dm_Normal2Xx(dmp, x);
-    sy = dm_Normal2Xy(dmp, y, use_aspect);
 
+HIDDEN int
+tk_drawLine2D(struct dm *dmp, fastf_t X1, fastf_t Y1, fastf_t X2, fastf_t Y2)
+{
+    return drawLine2D(dmp, X1, Y1, X2, Y2, "tk_drawLine2D()\n");
+}
 
-    Tk_DrawChars(pubvars->dpy,
-                privars->pix,
-                privars->gc,
-                privars->tkfontstruct,
-                str, strlen(str), sx, sy);
 
-    return BRLCAD_OK;
+HIDDEN int
+tk_drawLine3D(struct dm *dmp, point_t pt1, point_t pt2)
+{
+    return drawLine3D(dmp, pt1, pt2, "tk_drawLine3D()\n", wireColor);
 }
 
 
 HIDDEN int
-tk_drawLine2D(struct dm *dmp, fastf_t xpos1, fastf_t ypos1, fastf_t xpos2, 
fastf_t ypos2)
+tk_drawLines3D(struct dm *dmp, int npoints, point_t *points, int sflag)
 {
-    struct dm_tkvars *pubvars = (struct dm_tkvars *)dmp->i->dm_vars.pub_vars;
-    struct tk_vars *privars = (struct tk_vars *)dmp->i->dm_vars.priv_vars;
-    int sx1, sy1, sx2, sy2;
+    return drawLines3D(dmp, npoints, points, sflag, "tk_drawLine3D()\n", 
wireColor);
+}
 
-    sx1 = dm_Normal2Xx(dmp, xpos1);
-    sx2 = dm_Normal2Xx(dmp, xpos2);
-    sy1 = dm_Normal2Xy(dmp, ypos1, 0);
-    sy2 = dm_Normal2Xy(dmp, ypos2, 0);
 
+HIDDEN int
+tk_drawPoint2D(struct dm *dmp, fastf_t x, fastf_t y)
+{
     if (dmp->i->dm_debugLevel) {
-       bu_log("tk_drawLine2D()\n");
-       bu_log("x1 = %g, y1 = %g\n", xpos1, ypos1);
-       bu_log("x2 = %g, y2 = %g\n", xpos2, ypos2);
-       bu_log("sx1 = %d, sy1 = %d\n", sx1, sy1);
-       bu_log("sx2 = %d, sy2 = %d\n", sx2, sy2);
-       bu_log("color = %lu\n", privars->fg);
+       bu_log("tk_drawPoint2D():\n");
+       bu_log("\tdmp: %p\tx - %lf\ty - %lf\n", (void *)dmp, x, y);
     }
 
-    XDrawLine(pubvars->dpy,
-             privars->pix,
-             privars->gc,
-             sx1, sy1, sx2, sy2);
+#if ENABLE_POINT_SMOOTH
+    glEnable(GL_POINT_SMOOTH);
+#endif
+    glBegin(GL_POINTS);
+    glVertex2f(x, y);
+    glEnd();
 
     return BRLCAD_OK;
 }
@@ -767,20 +2132,27 @@
 
 
 HIDDEN int
-tk_drawLine3D(struct dm *dmp, point_t UNUSED(pt1), point_t UNUSED(pt2))
+tk_drawPoint3D(struct dm *dmp, point_t point)
 {
-    if (!dmp)
+    GLdouble dpt[3];
+
+    if (!dmp || !point)
        return BRLCAD_ERROR;
 
-    return BRLCAD_OK;
-}
+    if (dmp->i->dm_debugLevel) {
+       bu_log("tk_drawPoint3D():\n");
+       bu_log("\tdmp: %p\tpt - %lf %lf %lf\n", (void*)dmp, V3ARGS(point));
+    }
 
+    /* fastf_t to double */
+    VMOVE(dpt, point);
 
-HIDDEN int
-tk_drawLines3D(struct dm *dmp, int npoints, point_t *points, int UNUSED(sflag))
-{
-    if (!dmp || npoints < 0 || (npoints > 0 && !points))
-       return BRLCAD_ERROR;
+#if ENABLE_POINT_SMOOTH
+    glEnable(GL_POINT_SMOOTH);
+#endif
+    glBegin(GL_POINTS);
+    glVertex3dv(dpt);
+    glEnd();
 
     return BRLCAD_OK;
 }
@@ -787,25 +2159,28 @@
 
 
 HIDDEN int
-tk_drawPoint2D(struct dm *dmp, fastf_t x, fastf_t y)
+tk_drawPoints3D(struct dm *dmp, int npoints, point_t *points)
 {
-    struct dm_tkvars *pubvars = (struct dm_tkvars *)dmp->i->dm_vars.pub_vars;
-    struct tk_vars *privars = (struct tk_vars *)dmp->i->dm_vars.priv_vars;
+    GLdouble dpt[3];
+    register int i;
 
-    int sx, sy;
+    if (!dmp || npoints < 0 || !points)
+       return BRLCAD_ERROR;
 
-    sx = dm_Normal2Xx(dmp, x);
-    sy = dm_Normal2Xy(dmp, y, 0);
-
     if (dmp->i->dm_debugLevel) {
-       bu_log("tk_drawPoint2D()\n");
-       bu_log("x = %g, y = %g\n", x, y);
-       bu_log("sx = %d, sy = %d\n", sx, sy);
+       bu_log("tk_drawPoint3D():\n");
     }
 
-    XDrawPoint(pubvars->dpy,
-              privars->pix,
-              privars->gc, sx, sy);
+#if ENABLE_POINT_SMOOTH
+    glEnable(GL_POINT_SMOOTH);
+#endif
+    glBegin(GL_POINTS);
+    for (i = 0; i < npoints; ++i) {
+       /* fastf_t to double */
+       VMOVE(dpt, points[i]);
+       glVertex3dv(dpt);
+    }
+    glEnd();
 
     return BRLCAD_OK;
 }
@@ -814,71 +2189,59 @@
 HIDDEN int
 tk_setFGColor(struct dm *dmp, unsigned char r, unsigned char g, unsigned char 
b, int strict, fastf_t transparency)
 {
-    struct dm_tkvars *pubvars = (struct dm_tkvars *)dmp->i->dm_vars.pub_vars;
-    struct tk_vars *privars = (struct tk_vars *)dmp->i->dm_vars.priv_vars;
+    /*if (dmp->i->dm_debugLevel)
+       bu_log("tk_setFGColor()\n");*/
 
-    XColor color;
-
-    INIT_XCOLOR(&color);
-
-    if (!dmp) {
-       bu_log("WARNING: NULL display (r/g/b => %d/%d/%d; strict => %d; 
transparency => %f)\n", r, g, b, strict, transparency);
-       return BRLCAD_ERROR;
-    }
-
-    if (dmp->i->dm_debugLevel)
-       bu_log("tk_setFGColor(%d %d %d)\n", r, g, b);
-
     dmp->i->dm_fg[0] = r;
     dmp->i->dm_fg[1] = g;
     dmp->i->dm_fg[2] = b;
 
-    color.red = r << 8;
-    color.green = g << 8;
-    color.blue = b << 8;
+    /* wireColor gets the full rgb */
+    wireColor[0] = r / 255.0;
+    wireColor[1] = g / 255.0;
+    wireColor[2] = b / 255.0;
+    wireColor[3] = transparency;
 
-    privars->fg = Tk_GetColorByValue
-       (pubvars->xtkwin, &color)->pixel;
+    if (strict) {
+       glColor3ub((GLubyte)r, (GLubyte)g, (GLubyte)b);
+    } else {
 
-    XSetForeground(pubvars->dpy,
-                  privars->gc,
-                  privars->fg);
+       if (dmp->i->dm_light) {
+           /* Ambient = .2, Diffuse = .6, Specular = .2 */
 
-    return BRLCAD_OK;
-}
+           ambientColor[0] = wireColor[0] * 0.2;
+           ambientColor[1] = wireColor[1] * 0.2;
+           ambientColor[2] = wireColor[2] * 0.2;
+           ambientColor[3] = wireColor[3];
 
+           specularColor[0] = ambientColor[0];
+           specularColor[1] = ambientColor[1];
+           specularColor[2] = ambientColor[2];
+           specularColor[3] = ambientColor[3];
 
-HIDDEN int
-tk_setBGColor(struct dm *dmp, unsigned char r, unsigned char g, unsigned char 
b)
-{
-    XColor color;
+           diffuseColor[0] = wireColor[0] * 0.6;
+           diffuseColor[1] = wireColor[1] * 0.6;
+           diffuseColor[2] = wireColor[2] * 0.6;
+           diffuseColor[3] = wireColor[3];
 
-    INIT_XCOLOR(&color);
+           backDiffuseColorDark[0] = wireColor[0] * 0.3;
+           backDiffuseColorDark[1] = wireColor[1] * 0.3;
+           backDiffuseColorDark[2] = wireColor[2] * 0.3;
+           backDiffuseColorDark[3] = wireColor[3];
 
-    if (!dmp) {
-       bu_log("WARNING: NULL display (r/g/b==%d/%d/%d)\n", r, g, b);
-       return BRLCAD_ERROR;
+           backDiffuseColorLight[0] = wireColor[0] * 0.9;
+           backDiffuseColorLight[1] = wireColor[1] * 0.9;
+           backDiffuseColorLight[2] = wireColor[2] * 0.9;
+           backDiffuseColorLight[3] = wireColor[3];
+
+           glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambientColor);
+           glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specularColor);
+           glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuseColor);
+       } else {
+           glColor3ub((GLubyte)r,  (GLubyte)g,  (GLubyte)b);
+       }
     }
 
-    struct dm_tkvars *pubvars = (struct dm_tkvars *)dmp->i->dm_vars.pub_vars;
-    struct tk_vars *privars = (struct tk_vars *)dmp->i->dm_vars.priv_vars;
-
-    if (dmp->i->dm_debugLevel)
-       bu_log("tk_setBGColor()\n");
-
-    dmp->i->dm_bg[0] = r;
-    dmp->i->dm_bg[1] = g;
-    dmp->i->dm_bg[2] = b;
-
-    color.red = r << 8;
-    color.green = g << 8;
-    color.blue = b << 8;
-
-    XSetBackground(pubvars->dpy,
-                  privars->gc,
-                  Tk_GetColorByValue(pubvars->xtkwin,
-                                     &color)->pixel);
-
     return BRLCAD_OK;
 }
 
@@ -886,34 +2249,23 @@
 HIDDEN int
 tk_setLineAttr(struct dm *dmp, int width, int style)
 {
-    struct dm_tkvars *pubvars = (struct dm_tkvars *)dmp->i->dm_vars.pub_vars;
-    struct tk_vars *privars = (struct tk_vars *)dmp->i->dm_vars.priv_vars;
+    /*if (dmp->i->dm_debugLevel)
+       bu_log("tk_setLineAttr()\n");*/
 
-    int linestyle;
-
-    if (dmp->i->dm_debugLevel)
-       bu_log("tk_setLineAttr(width: %d, style: %d)\n", width, style);
-
     dmp->i->dm_lineWidth = width;
     dmp->i->dm_lineStyle = style;
 
-    if (width < 1)
-       width = 1;
+    glLineWidth((GLfloat) width);
 
     if (style == DM_DASHED_LINE)
-       linestyle = LineOnOffDash;
+       glEnable(GL_LINE_STIPPLE);
     else
-       linestyle = LineSolid;
+       glDisable(GL_LINE_STIPPLE);
 
-    XSetLineAttributes(pubvars->dpy,
-                      privars->gc,
-                      width, linestyle, CapButt, JoinMiter);
-
     return BRLCAD_OK;
 }
 
 
-/* ARGSUSED */
 HIDDEN int
 tk_debug(struct dm *dmp, int lvl)
 {
@@ -930,11 +2282,11 @@
     return BRLCAD_OK;
 }
 
-
-
 HIDDEN int
 tk_setWinBounds(struct dm *dmp, fastf_t *w)
 {
+    GLint mm;
+
     if (dmp->i->dm_debugLevel)
        bu_log("tk_setWinBounds()\n");
 
@@ -945,110 +2297,409 @@
     dmp->i->dm_clipmax[1] = w[3];
     dmp->i->dm_clipmax[2] = w[5];
 
+    glGetIntegerv(GL_MATRIX_MODE, &mm);
+    glMatrixMode(GL_PROJECTION);
+    glPopMatrix();
+    glLoadIdentity();
+    glOrtho(-xlim_view, xlim_view, -ylim_view, ylim_view, 
dmp->i->dm_clipmin[2], dmp->i->dm_clipmax[2]);
+    glPushMatrix();
+    glMatrixMode(mm);
+
     return BRLCAD_OK;
 }
 
 
 HIDDEN int
-tk_configureWin_guts(struct dm *dmp, int force)
+tk_setTransparency(struct dm *dmp,
+                   int transparency_on)
 {
-    int h, w;
-    Tcl_Interp *interp = (Tcl_Interp *)dmp->i->dm_interp;
+    struct modifiable_tk_vars *mvars = (struct modifiable_tk_vars 
*)dmp->i->m_vars;
+    if (dmp->i->dm_debugLevel)
+       bu_log("tk_setTransparency()\n");
 
-    struct dm_tkvars *pubvars = (struct dm_tkvars *)dmp->i->dm_vars.pub_vars;
-    struct tk_vars *privars = (struct tk_vars *)dmp->i->dm_vars.priv_vars;
+    dmp->i->dm_transparency = transparency_on;
+    mvars->transparency_on = dmp->i->dm_transparency;
 
+    if (transparency_on) {
+       /* Turn it on */
+       glEnable(GL_BLEND);
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    } else {
+       /* Turn it off */
+       glDisable(GL_BLEND);
+    }
 
-    /* nothing to do */
-    h = Tk_Height(pubvars->xtkwin);
-    w = Tk_Width(pubvars->xtkwin);
+    return BRLCAD_OK;
+}
 
-    if (!force && dmp->i->dm_width==w && dmp->i->dm_height == h)
-       return BRLCAD_OK;
 
-    dmp->i->dm_width=w;
-    dmp->i->dm_width=h;
+HIDDEN int
+tk_setDepthMask(struct dm *dmp,
+                int enable) {
+    if (dmp->i->dm_debugLevel)
+       bu_log("tk_setDepthMask()\n");
 
-    dmp->i->dm_aspect = (fastf_t)dmp->i->dm_width / (fastf_t)dmp->i->dm_height;
+    dmp->i->dm_depthMask = enable;
 
-    if (dmp->i->dm_debugLevel) {
-       bu_log("tk_configureWin_guts()\n");
-       bu_log("width = %d, height = %d\n", dmp->i->dm_width, 
dmp->i->dm_height);
-    }
+    if (enable)
+       glDepthMask(GL_TRUE);
+    else
+       glDepthMask(GL_FALSE);
 
-    Tk_FreePixmap(pubvars->dpy,
-                 privars->pix);
-    privars->pix =
-       Tk_GetPixmap(pubvars->dpy,
-                    DefaultRootWindow(pubvars->dpy),
-                    dmp->i->dm_width,
-                    dmp->i->dm_height,
-                    Tk_Depth(pubvars->xtkwin));
+    return BRLCAD_OK;
+}
 
-    /* First time through, load a font or quit */
-    if (privars->tkfontset == 0) {
 
-       privars->tkfontstruct =
-           Tk_GetFont(interp, pubvars->xtkwin, FONT9);
+HIDDEN int
+tk_setZBuffer(struct dm *dmp, int zbuffer_on)
+{
+    struct modifiable_tk_vars *mvars = (struct modifiable_tk_vars 
*)dmp->i->m_vars;
+    if (dmp->i->dm_debugLevel)
+       bu_log("tk_setZBuffer:\n");
 
-       if (privars->tkfontstruct == NULL) {
-           /* Try hardcoded backup font */
+    dmp->i->dm_zbuffer = zbuffer_on;
+    mvars->zbuffer_on = dmp->i->dm_zbuffer;
 
-           privars->tkfontstruct =
-               Tk_GetFont(interp, pubvars->xtkwin, FONTBACK);
+    if (mvars->zbuf == 0) {
+       dmp->i->dm_zbuffer = 0;
+       mvars->zbuffer_on = dmp->i->dm_zbuffer;
+    }
 
-           if (privars->tkfontstruct == NULL) {
-               bu_log("dm-Tk: Can't open font '%s' or '%s'\n", FONT9, 
FONTBACK);
-               return BRLCAD_ERROR;
-           }
-       }
-       privars->tkfontset = 1;
+    if (mvars->zbuffer_on) {
+       glDepthFunc(GL_LEQUAL);
+       glEnable(GL_DEPTH_TEST);
+    } else {
+       glDisable(GL_DEPTH_TEST);
     }
 
-    /* XXX:  I removed the font-sizing routine from dm-X from here.  Something
-       should be devised to replace it.  --TJM*/
-
     return BRLCAD_OK;
 }
 
 
 HIDDEN int
-tk_configureWin(struct dm *dmp, int force)
+tk_beginDList(struct dm *dmp, unsigned int list)
 {
-    /* don't force */
-    return tk_configureWin_guts(dmp, force);
+    if (dmp->i->dm_debugLevel)
+       bu_log("tk_beginDList()\n");
+
+    glNewList((GLuint)list, GL_COMPILE);
+    return BRLCAD_OK;
 }
 
 
 HIDDEN int
-tk_setLight(struct dm *dmp, int light_on)
+tk_endDList(struct dm *dmp)
 {
     if (dmp->i->dm_debugLevel)
-       bu_log("tk_setLight:\n");
+       bu_log("tk_endDList()\n");
 
-    dmp->i->dm_light = light_on;
+    glEndList();
+    return BRLCAD_OK;
+}
 
+
+HIDDEN int
+tk_drawDList(unsigned int list)
+{
+    glCallList((GLuint)list);
     return BRLCAD_OK;
 }
 
 
 HIDDEN int
-tk_setZBuffer(struct dm *dmp, int zbuffer_on)
+tk_freeDLists(struct dm *dmp, unsigned int list, int range)
 {
     if (dmp->i->dm_debugLevel)
-       bu_log("tk_setZBuffer:\n");
+       bu_log("tk_freeDLists()\n");
 
-    dmp->i->dm_zbuffer = zbuffer_on;
-
+    glDeleteLists((GLuint)list, (GLsizei)range);
     return BRLCAD_OK;
 }
 
+
+HIDDEN int
+tk_genDLists(struct dm *dmp, size_t range)
+{
+    if (dmp->i->dm_debugLevel)
+       bu_log("tk_freeDLists()\n");
+
+    return glGenLists((GLsizei)range);
+}
+
+HIDDEN int
+tk_draw_obj(struct dm *dmp, struct display_list *obj)
+{
+    struct solid *sp;
+    FOR_ALL_SOLIDS(sp, &obj->dl_headSolid) {
+       if (sp->s_dlist == 0)
+           sp->s_dlist = dm_gen_dlists(dmp, 1);
+
+       (void)dm_make_current(dmp);
+       (void)dm_begin_dlist(dmp, sp->s_dlist);
+       if (sp->s_iflag == UP)
+           (void)dm_set_fg(dmp, 255, 255, 255, 0, sp->s_transparency);
+       else
+           (void)dm_set_fg(dmp,
+                   (unsigned char)sp->s_color[0],
+                   (unsigned char)sp->s_color[1],
+                   (unsigned char)sp->s_color[2], 0, sp->s_transparency);
+       (void)dm_draw_vlist(dmp, (struct bn_vlist *)&sp->s_vlist);
+       (void)dm_end_dlist(dmp);
+    }
+    return 0;
+}
+
+HIDDEN int
+tk_getDisplayImage(struct dm *dmp, unsigned char **image)
+{
+    unsigned char *idata;
+    int width;
+    int height;
+
+    width = dmp->i->dm_width;
+    height = dmp->i->dm_height;
+
+    idata = (unsigned char*)bu_calloc(height * width * 3, sizeof(unsigned 
char), "rgb data");
+
+    glReadBuffer(GL_FRONT);
+    glPixelStorei(GL_PACK_ALIGNMENT, 1);
+    glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, idata);
+    *image = idata;
+    flip_display_image_vertically(*image, width, height);
+
+    return BRLCAD_OK; /* caller will need to bu_free(idata, "image data"); */
+}
+
+int
+tk_openFb(struct dm *dmp)
+{
+    struct fb_platform_specific *fb_ps;
+    struct tk_fb_info *ofb_ps;
+    struct modifiable_tk_vars *mvars = (struct modifiable_tk_vars 
*)dmp->i->m_vars;
+    struct dm_tkvars *pubvars = (struct dm_tkvars *)dmp->i->dm_vars.pub_vars;
+    struct tk_vars *privars = (struct tk_vars *)dmp->i->dm_vars.priv_vars;
+
+    fb_ps = fb_get_platform_specific(FB_OGL_MAGIC);
+    ofb_ps = (struct tk_fb_info *)fb_ps->data;
+    ofb_ps->dpy = pubvars->dpy;
+    ofb_ps->win = pubvars->win;
+    ofb_ps->cmap = pubvars->cmap;
+    ofb_ps->vip = pubvars->vip;
+    ofb_ps->glxc = privars->glxc;
+    ofb_ps->double_buffer = mvars->doublebuffer;
+    ofb_ps->soft_cmap = 0;
+    dmp->i->fbp = fb_open_existing("tk", dm_get_width(dmp), 
dm_get_height(dmp), fb_ps);
+    fb_put_platform_specific(fb_ps);
+    return 0;
+}
+
+int
+tk_get_internal(struct dm *dmp)
+{
+    struct modifiable_tk_vars *mvars = NULL;
+    if (!dmp->i->m_vars) {
+       BU_GET(dmp->i->m_vars, struct modifiable_tk_vars);
+       mvars = (struct modifiable_tk_vars *)dmp->i->m_vars;
+       mvars->this_dm = dmp;
+       bu_vls_init(&(mvars->log));
+    }
+    return 0;
+}
+
+int
+tk_put_internal(struct dm *dmp)
+{
+    struct modifiable_tk_vars *mvars = NULL;
+    if (dmp->i->m_vars) {
+       mvars = (struct modifiable_tk_vars *)dmp->i->m_vars;
+       bu_vls_free(&(mvars->log));
+       BU_PUT(dmp->i->m_vars, struct modifiable_tk_vars);
+    }
+    return 0;
+}
+
+void
+Tk_colorchange(const struct bu_structparse *sdp,
+       const char *name,
+       void *base,
+       const char *value,
+       void *data)
+{
+    struct modifiable_tk_vars *mvars = (struct modifiable_tk_vars *)base;
+    if (mvars->cueing_on) {
+       glEnable(GL_FOG);
+    } else {
+       glDisable(GL_FOG);
+    }
+
+    dm_generic_hook(sdp, name, base, value, data);
+}
+
+static void
+tk_zclip_hook(const struct bu_structparse *sdp,
+       const char *name,
+       void *base,
+       const char *value,
+       void *data)
+{
+    struct modifiable_tk_vars *mvars = (struct modifiable_tk_vars *)base;
+    struct dm *dmp = mvars->this_dm;
+    fastf_t bounds[6] = { GED_MIN, GED_MAX, GED_MIN, GED_MAX, GED_MIN, GED_MAX 
};
+
+    dmp->i->dm_zclip = mvars->zclipping_on;
+
+    if (dmp->i->dm_zclip) {
+       bounds[4] = -1.0;
+       bounds[5] = 1.0;
+    }
+
+    (void)dm_make_current(dmp);
+    (void)dm_set_win_bounds(dmp, bounds);
+
+    dm_generic_hook(sdp, name, base, value, data);
+}
+
+static void
+tk_debug_hook(const struct bu_structparse *sdp,
+       const char *name,
+       void *base,
+       const char *value,
+       void *data)
+{
+    struct modifiable_tk_vars *mvars = (struct modifiable_tk_vars *)base;
+    struct dm *dmp = mvars->this_dm;
+
+    dm_debug(dmp, mvars->debug);
+
+    dm_generic_hook(sdp, name, base, value, data);
+}
+
+
+static void
+tk_logfile_hook(const struct bu_structparse *sdp,
+       const char *name,
+       void *base,
+       const char *value,
+       void *data)
+{
+    struct modifiable_tk_vars *mvars = (struct modifiable_tk_vars *)base;
+    struct dm *dmp = mvars->this_dm;
+
+    dm_logfile(dmp, bu_vls_addr(&mvars->log));
+
+    dm_generic_hook(sdp, name, base, value, data);
+}
+
+static void
+tk_bound_hook(const struct bu_structparse *sdp,
+       const char *name,
+       void *base,
+       const char *value,
+       void *data)
+{
+    struct modifiable_tk_vars *mvars = (struct modifiable_tk_vars *)base;
+    struct dm *dmp = mvars->this_dm;
+
+    dmp->i->dm_bound = mvars->bound;
+
+    dm_generic_hook(sdp, name, base, value, data);
+}
+
+static void
+tk_bound_flag_hook(const struct bu_structparse *sdp,
+       const char *name,
+       void *base,
+       const char *value,
+       void *data)
+{
+    struct modifiable_tk_vars *mvars = (struct modifiable_tk_vars *)base;
+    struct dm *dmp = mvars->this_dm;
+
+    dmp->i->dm_boundFlag = mvars->boundFlag;
+
+    dm_generic_hook(sdp, name, base, value, data);
+}
+
+static void
+tk_zbuffer_hook(const struct bu_structparse *sdp,
+       const char *name,
+       void *base,
+       const char *value,
+       void *data)
+{
+    struct modifiable_tk_vars *mvars = (struct modifiable_tk_vars *)base;
+    struct dm *dmp = mvars->this_dm;
+
+    (void)dm_make_current(dmp);
+    (void)dm_set_zbuffer(dmp, mvars->zbuffer_on);
+
+    dm_generic_hook(sdp, name, base, value, data);
+}
+
+static void
+tk_lighting_hook(const struct bu_structparse *sdp,
+       const char *name,
+       void *base,
+       const char *value,
+       void *data)
+{
+    struct modifiable_tk_vars *mvars = (struct modifiable_tk_vars *)base;
+    struct dm *dmp = mvars->this_dm;
+
+    (void)dm_make_current(dmp);
+    (void)dm_set_light(dmp, mvars->lighting_on);
+
+    dm_generic_hook(sdp, name, base, value, data);
+}
+
+static void
+tk_transparency_hook(const struct bu_structparse *sdp,
+       const char *name,
+       void *base,
+       const char *value,
+       void *data)
+{
+    struct modifiable_tk_vars *mvars = (struct modifiable_tk_vars *)base;
+    struct dm *dmp = mvars->this_dm;
+
+    (void)dm_make_current(dmp);
+    (void)dm_set_transparency(dmp, mvars->transparency_on);
+
+    dm_generic_hook(sdp, name, base, value, data);
+}
+
+static void
+tk_fog_hook(const struct bu_structparse *sdp,
+       const char *name,
+       void *base,
+       const char *value,
+       void *data)
+{
+    struct modifiable_tk_vars *mvars = (struct modifiable_tk_vars *)base;
+    struct dm *dmp = mvars->this_dm;
+
+    dm_fogHint(dmp, mvars->fastfog);
+
+    dm_generic_hook(sdp, name, base, value, data);
+}
+
 struct bu_structparse Tk_vparse[] = {
-    {"%g",  1, "bound",         DM_O(dm_bound),         dm_generic_hook, NULL, 
NULL},
-    {"%d",  1, "useBound",      DM_O(dm_boundFlag),     dm_generic_hook, NULL, 
NULL},
-    {"%d",  1, "zclip",         DM_O(dm_zclip),         dm_generic_hook, NULL, 
NULL},
-    {"%d",  1, "debug",         DM_O(dm_debugLevel),    dm_generic_hook, NULL, 
NULL},
-    {"",    0, (char *)0,       0,                      
BU_STRUCTPARSE_FUNC_NULL, NULL, NULL}
+    {"%d",  1, "depthcue",              Tk_MV_O(cueing_on),    Tk_colorchange, 
NULL, NULL },
+    {"%d",  1, "zclip",                Tk_MV_O(zclipping_on), tk_zclip_hook, 
NULL, NULL },
+    {"%d",  1, "zbuffer",               Tk_MV_O(zbuffer_on),   
tk_zbuffer_hook, NULL, NULL },
+    {"%d",  1, "lighting",              Tk_MV_O(lighting_on),  
tk_lighting_hook, NULL, NULL },
+    {"%d",  1, "transparency",         Tk_MV_O(transparency_on), 
tk_transparency_hook, NULL, NULL },
+    {"%d",  1, "fastfog",               Tk_MV_O(fastfog),      tk_fog_hook, 
NULL, NULL },
+    {"%g",  1, "density",               Tk_MV_O(fogdensity),   
dm_generic_hook, NULL, NULL },
+    {"%d",  1, "has_zbuf",              Tk_MV_O(zbuf),         
dm_generic_hook, NULL, NULL },
+    {"%d",  1, "has_rgb",               Tk_MV_O(rgb),          
dm_generic_hook, NULL, NULL },
+    {"%d",  1, "has_doublebuffer",      Tk_MV_O(doublebuffer), 
dm_generic_hook, NULL, NULL },
+    {"%d",  1, "depth",                Tk_MV_O(depth),        dm_generic_hook, 
NULL, NULL },
+    {"%d",  1, "debug",                Tk_MV_O(debug),        tk_debug_hook, 
NULL, NULL },
+    {"%V",  1, "log",                  Tk_MV_O(log),    tk_logfile_hook, NULL, 
NULL },
+    {"%g",  1, "bound",                Tk_MV_O(bound),        tk_bound_hook, 
NULL, NULL },
+    {"%d",  1, "useBound",              Tk_MV_O(boundFlag),    
tk_bound_flag_hook, NULL, NULL },
+    {"",        0,  (char *)0,          0,                      
BU_STRUCTPARSE_FUNC_NULL, NULL, NULL }
 };
 
 int
@@ -1059,18 +2710,20 @@
     return 0;
 }
 
-#define TKVARS_MV_O(_m) offsetof(struct dm_tkvars, _m)
+#define GLXVARS_MV_O(_m) offsetof(struct dm_tkvars, _m)
 
 struct bu_structparse dm_tkvars_vparse[] = {
-    {"%x",      1,      "dpy",                  TKVARS_MV_O(dpy),        
BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
-    {"%x",      1,      "win",                  TKVARS_MV_O(win),        
BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
-    {"%x",      1,      "top",                  TKVARS_MV_O(top),        
BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
-    {"%x",      1,      "tkwin",                TKVARS_MV_O(xtkwin),     
BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
-    {"%d",      1,      "depth",                TKVARS_MV_O(depth),      
BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
-    {"%x",      1,      "cmap",                 TKVARS_MV_O(cmap),       
BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
-    {"%d",      1,      "devmotionnotify",      TKVARS_MV_O(devmotionnotify),  
  BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
-    {"%d",      1,      "devbuttonpress",       TKVARS_MV_O(devbuttonpress),   
  BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
-    {"%d",      1,      "devbuttonrelease",     TKVARS_MV_O(devbuttonrelease), 
  BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
+    {"%x",      1,      "dpy",                  GLXVARS_MV_O(dpy),        
BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
+    {"%x",      1,      "win",                  GLXVARS_MV_O(win),        
BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
+    {"%x",      1,      "top",                  GLXVARS_MV_O(top),        
BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
+    {"%x",      1,      "tkwin",                GLXVARS_MV_O(xtkwin),     
BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
+    {"%d",      1,      "depth",                GLXVARS_MV_O(depth),      
BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
+    {"%x",      1,      "cmap",                 GLXVARS_MV_O(cmap),       
BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
+    {"%x",      1,      "vip",                  GLXVARS_MV_O(vip),        
BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
+    {"%x",      1,      "fontstruct",           GLXVARS_MV_O(fontstruct), 
BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
+    {"%d",      1,      "devmotionnotify",      GLXVARS_MV_O(devmotionnotify), 
   BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
+    {"%d",      1,      "devbuttonpress",       GLXVARS_MV_O(devbuttonpress),  
   BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
+    {"%d",      1,      "devbuttonrelease",     
GLXVARS_MV_O(devbuttonrelease),   BU_STRUCTPARSE_FUNC_NULL, NULL, NULL },
     {"",        0,      (char *)0,              0,                      
BU_STRUCTPARSE_FUNC_NULL, NULL, NULL }
 };
 
@@ -1080,7 +2733,7 @@
     if (!dmp || !result) return -1;
     if (!key) {
         // Print all current vars
-        bu_vls_struct_print2(result, "dm internal Tk variables", 
dm_tkvars_vparse, (const char *)dmp->i->dm_vars.pub_vars);
+        bu_vls_struct_print2(result, "dm internal GLX variables", 
dm_tkvars_vparse, (const char *)dmp->i->dm_vars.pub_vars);
         return 0;
     }
     // Print specific var
@@ -1088,7 +2741,265 @@
     return 0;
 }
 
+
+// TODO - this and getDisplayImage need to be consolidated...
 int
+tk_write_image(struct bu_vls *msgs, FILE *fp, struct dm *dmp)
+{
+    png_structp png_p;
+    png_infop info_p;
+    XImage *ximage_p;
+    unsigned char **rows;
+    unsigned char *idata;
+    unsigned char *irow;
+    int bytes_per_pixel;
+    int bits_per_channel = 8;  /* bits per color channel */
+    int i, j, k;
+    unsigned char *dbyte0, *dbyte1, *dbyte2, *dbyte3;
+    int red_shift;
+    int green_shift;
+    int blue_shift;
+    int red_bits;
+    int green_bits;
+    int blue_bits;
+
+    png_p = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+    if (!png_p) {
+       if (msgs) {
+           bu_vls_printf(msgs, "tk_write_image: could not create PNG write 
structure\n");
+       }
+       return -1;
+    }
+
+    info_p = png_create_info_struct(png_p);
+    if (!info_p) {
+       if (msgs) {
+           bu_vls_printf(msgs, "tk_write_image: could not create PNG info 
structure\n");
+       }
+       png_destroy_write_struct(&png_p, NULL);
+       return -1;
+    }
+
+    ximage_p = XGetImage(((struct dm_tkvars *)dmp->i->dm_vars.pub_vars)->dpy,
+                        ((struct dm_tkvars *)dmp->i->dm_vars.pub_vars)->win,
+                        0, 0,
+                        dmp->i->dm_width,
+                        dmp->i->dm_height,
+                        ~0, ZPixmap);
+    if (!ximage_p) {
+       if (msgs) {
+           bu_vls_printf(msgs, "png: could not get XImage\n");
+       }
+       png_destroy_write_struct(&png_p, &info_p);
+       return -1;
+    }
+
+    bytes_per_pixel = ximage_p->bytes_per_line / ximage_p->width;
+
+    if (bytes_per_pixel == 4) {
+       unsigned long mask;
+       unsigned long tmask;
+
+       /* This section assumes 8 bits per channel */
+
+       mask = ximage_p->red_mask;
+       tmask = 1;
+       for (red_shift = 0; red_shift < 32; red_shift++) {
+           if (tmask & mask)
+               break;
+           tmask = tmask << 1;
+       }
+
+       mask = ximage_p->green_mask;
+       tmask = 1;
+       for (green_shift = 0; green_shift < 32; green_shift++) {
+           if (tmask & mask)
+               break;
+           tmask = tmask << 1;
+       }
+
+       mask = ximage_p->blue_mask;
+       tmask = 1;
+       for (blue_shift = 0; blue_shift < 32; blue_shift++) {
+           if (tmask & mask)
+               break;
+           tmask = tmask << 1;
+       }
+
+       /*
+        * We need to reverse things if the image byte order
+        * is different from the system's byte order.
+        */
+       if (((bu_byteorder() == BU_BIG_ENDIAN) && (ximage_p->byte_order == 
LSBFirst)) ||
+           ((bu_byteorder() == BU_LITTLE_ENDIAN) && (ximage_p->byte_order == 
MSBFirst))) {
+           DM_REVERSE_COLOR_BYTE_ORDER(red_shift, ximage_p->red_mask);
+           DM_REVERSE_COLOR_BYTE_ORDER(green_shift, ximage_p->green_mask);
+           DM_REVERSE_COLOR_BYTE_ORDER(blue_shift, ximage_p->blue_mask);
+       }
+
+    } else if (bytes_per_pixel == 2) {
+       unsigned long mask;
+       unsigned long tmask;
+       int bpb = 8;   /* bits per byte */
+
+       /*XXX
+        * This section probably needs logic similar
+        * to the previous section (i.e. bytes_per_pixel == 4).
+        * That is we may need to reverse things depending on
+        * the image byte order and the system's byte order.
+        */
+
+       mask = ximage_p->red_mask;
+       tmask = 1;
+       for (red_shift = 0; red_shift < 16; red_shift++) {
+           if (tmask & mask)
+               break;
+           tmask = tmask << 1;
+       }
+       for (red_bits = red_shift; red_bits < 16; red_bits++) {
+           if (!(tmask & mask))
+               break;
+           tmask = tmask << 1;
+       }
+
+       red_bits = red_bits - red_shift;
+       if (red_shift == 0)
+           red_shift = red_bits - bpb;
+       else
+           red_shift = red_shift - (bpb - red_bits);
+
+       mask = ximage_p->green_mask;
+       tmask = 1;
+       for (green_shift = 0; green_shift < 16; green_shift++) {
+           if (tmask & mask)
+               break;
+           tmask = tmask << 1;
+       }
+       for (green_bits = green_shift; green_bits < 16; green_bits++) {
+           if (!(tmask & mask))
+               break;
+           tmask = tmask << 1;
+       }
+
+       green_bits = green_bits - green_shift;
+       green_shift = green_shift - (bpb - green_bits);
+
+       mask = ximage_p->blue_mask;
+       tmask = 1;
+       for (blue_shift = 0; blue_shift < 16; blue_shift++) {
+           if (tmask & mask)
+               break;
+           tmask = tmask << 1;
+       }
+       for (blue_bits = blue_shift; blue_bits < 16; blue_bits++) {
+           if (!(tmask & mask))
+               break;
+           tmask = tmask << 1;
+       }
+       blue_bits = blue_bits - blue_shift;
+
+       if (blue_shift == 0)
+           blue_shift = blue_bits - bpb;
+       else
+           blue_shift = blue_shift - (bpb - blue_bits);
+    } else {
+       if (msgs) {
+           bu_vls_printf(msgs, "png: %d bytes per pixel is not yet 
supported\n", bytes_per_pixel);
+       }
+       png_destroy_write_struct(&png_p, &info_p);
+       return -1;
+    }
+
+    rows = (unsigned char **)bu_calloc(ximage_p->height, sizeof(unsigned char 
*), "rows");
+    idata = (unsigned char *)bu_calloc(ximage_p->height * ximage_p->width, 4, 
"png data");
+
+    /* for each scanline */
+    for (i = ximage_p->height - 1, j = 0; 0 <= i; --i, ++j) {

@@ Diff output truncated at 100000 characters. @@
This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.



_______________________________________________
BRL-CAD Source Commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/brlcad-commits

Reply via email to