Revision: 75427
          http://sourceforge.net/p/brlcad/code/75427
Author:   starseeker
Date:     2020-04-16 21:11:44 +0000 (Thu, 16 Apr 2020)
Log Message:
-----------
Group common "backend" files in subdirectories

Modified Paths:
--------------
    brlcad/branches/dm-fb-merge/src/libdm/CMakeLists.txt
    brlcad/branches/dm-fb-merge/src/libdm/dm_obj.c

Added Paths:
-----------
    brlcad/branches/dm-fb-merge/src/libdm/X/
    brlcad/branches/dm-fb-merge/src/libdm/X/dm-X.c
    brlcad/branches/dm-fb-merge/src/libdm/X/dm-X.h
    brlcad/branches/dm-fb-merge/src/libdm/X/fb_X.h
    brlcad/branches/dm-fb-merge/src/libdm/X/if_X24.c
    brlcad/branches/dm-fb-merge/src/libdm/glx/
    brlcad/branches/dm-fb-merge/src/libdm/glx/dm-glx.h
    brlcad/branches/dm-fb-merge/src/libdm/glx/dm-ogl.c
    brlcad/branches/dm-fb-merge/src/libdm/glx/dm-ogl.h
    brlcad/branches/dm-fb-merge/src/libdm/glx/fb_ogl.h
    brlcad/branches/dm-fb-merge/src/libdm/glx/if_ogl.c
    brlcad/branches/dm-fb-merge/src/libdm/null/
    brlcad/branches/dm-fb-merge/src/libdm/null/dm-Null.c
    brlcad/branches/dm-fb-merge/src/libdm/null/dm-Null.h
    brlcad/branches/dm-fb-merge/src/libdm/null/if_null.c
    brlcad/branches/dm-fb-merge/src/libdm/osgl/
    brlcad/branches/dm-fb-merge/src/libdm/osgl/dm-osgl.cpp
    brlcad/branches/dm-fb-merge/src/libdm/osgl/dm-osgl.h
    brlcad/branches/dm-fb-merge/src/libdm/osgl/fb_osgl.h
    brlcad/branches/dm-fb-merge/src/libdm/osgl/if_osgl.cpp
    brlcad/branches/dm-fb-merge/src/libdm/osgl/osg-test.cpp
    brlcad/branches/dm-fb-merge/src/libdm/osgl/osg_bob.cpp
    brlcad/branches/dm-fb-merge/src/libdm/osgl/osg_fb_manipulator.h
    brlcad/branches/dm-fb-merge/src/libdm/plot/
    brlcad/branches/dm-fb-merge/src/libdm/plot/dm-plot.c
    brlcad/branches/dm-fb-merge/src/libdm/plot/dm-plot.h
    brlcad/branches/dm-fb-merge/src/libdm/postscript/
    brlcad/branches/dm-fb-merge/src/libdm/postscript/dm-ps.c
    brlcad/branches/dm-fb-merge/src/libdm/postscript/dm-ps.h
    brlcad/branches/dm-fb-merge/src/libdm/qt/
    brlcad/branches/dm-fb-merge/src/libdm/qt/dm-qt.cpp
    brlcad/branches/dm-fb-merge/src/libdm/qt/dm-qt.h
    brlcad/branches/dm-fb-merge/src/libdm/qt/fb_qt.h
    brlcad/branches/dm-fb-merge/src/libdm/qt/if_qt.cpp
    brlcad/branches/dm-fb-merge/src/libdm/tk/
    brlcad/branches/dm-fb-merge/src/libdm/tk/dm-tk.c
    brlcad/branches/dm-fb-merge/src/libdm/tk/dm-tk.h
    brlcad/branches/dm-fb-merge/src/libdm/tk/if_tk.c
    brlcad/branches/dm-fb-merge/src/libdm/txt/
    brlcad/branches/dm-fb-merge/src/libdm/txt/dm-txt.c
    brlcad/branches/dm-fb-merge/src/libdm/txt/if_debug.c
    brlcad/branches/dm-fb-merge/src/libdm/wgl/
    brlcad/branches/dm-fb-merge/src/libdm/wgl/dm-wgl.c
    brlcad/branches/dm-fb-merge/src/libdm/wgl/dm-wgl.h
    brlcad/branches/dm-fb-merge/src/libdm/wgl/fb_wgl.h
    brlcad/branches/dm-fb-merge/src/libdm/wgl/if_wgl.c

Removed Paths:
-------------
    brlcad/branches/dm-fb-merge/src/libdm/dm-Null.c
    brlcad/branches/dm-fb-merge/src/libdm/dm-Null.h
    brlcad/branches/dm-fb-merge/src/libdm/dm-X.c
    brlcad/branches/dm-fb-merge/src/libdm/dm-X.h
    brlcad/branches/dm-fb-merge/src/libdm/dm-glx.h
    brlcad/branches/dm-fb-merge/src/libdm/dm-ogl.c
    brlcad/branches/dm-fb-merge/src/libdm/dm-ogl.h
    brlcad/branches/dm-fb-merge/src/libdm/dm-osgl.cpp
    brlcad/branches/dm-fb-merge/src/libdm/dm-osgl.h
    brlcad/branches/dm-fb-merge/src/libdm/dm-plot.c
    brlcad/branches/dm-fb-merge/src/libdm/dm-plot.h
    brlcad/branches/dm-fb-merge/src/libdm/dm-ps.c
    brlcad/branches/dm-fb-merge/src/libdm/dm-ps.h
    brlcad/branches/dm-fb-merge/src/libdm/dm-qt.cpp
    brlcad/branches/dm-fb-merge/src/libdm/dm-qt.h
    brlcad/branches/dm-fb-merge/src/libdm/dm-tk.c
    brlcad/branches/dm-fb-merge/src/libdm/dm-tk.h
    brlcad/branches/dm-fb-merge/src/libdm/dm-txt.c
    brlcad/branches/dm-fb-merge/src/libdm/dm-wgl.c
    brlcad/branches/dm-fb-merge/src/libdm/dm-wgl.h
    brlcad/branches/dm-fb-merge/src/libdm/fb_X.h
    brlcad/branches/dm-fb-merge/src/libdm/fb_ogl.h
    brlcad/branches/dm-fb-merge/src/libdm/fb_osgl.h
    brlcad/branches/dm-fb-merge/src/libdm/fb_qt.h
    brlcad/branches/dm-fb-merge/src/libdm/fb_wgl.h
    brlcad/branches/dm-fb-merge/src/libdm/if_X24.c
    brlcad/branches/dm-fb-merge/src/libdm/if_debug.c
    brlcad/branches/dm-fb-merge/src/libdm/if_null.c
    brlcad/branches/dm-fb-merge/src/libdm/if_ogl.c
    brlcad/branches/dm-fb-merge/src/libdm/if_osgl.cpp
    brlcad/branches/dm-fb-merge/src/libdm/if_qt.cpp
    brlcad/branches/dm-fb-merge/src/libdm/if_tk.c
    brlcad/branches/dm-fb-merge/src/libdm/if_wgl.c
    brlcad/branches/dm-fb-merge/src/libdm/osg-test.cpp
    brlcad/branches/dm-fb-merge/src/libdm/osg_bob.cpp
    brlcad/branches/dm-fb-merge/src/libdm/osg_fb_manipulator.h

Modified: brlcad/branches/dm-fb-merge/src/libdm/CMakeLists.txt
===================================================================
--- brlcad/branches/dm-fb-merge/src/libdm/CMakeLists.txt        2020-04-16 
02:48:48 UTC (rev 75426)
+++ brlcad/branches/dm-fb-merge/src/libdm/CMakeLists.txt        2020-04-16 
21:11:44 UTC (rev 75427)
@@ -17,7 +17,7 @@
   )
 
 # local includes
-set(DM_LOCAL_INCLUDE_DIRS ${PNG_INCLUDE_DIRS})
+set(DM_LOCAL_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} 
${CMAKE_CURRENT_SOURCE_DIR}/null ${PNG_INCLUDE_DIRS})
 
 BRLCAD_LIB_INCLUDE_DIRS(dm DM_INCLUDE_DIRS DM_LOCAL_INCLUDE_DIRS)
 
@@ -29,10 +29,10 @@
 # Add the individual OS specific files and definitions
 if(WIN32 AND BRLCAD_ENABLE_OPENGL)
   list(APPEND libdm_DEFINES DM_WGL IF_WGL)
-  set(dmw32_srcs dm-wgl.c if_wgl.c)
+  set(dmw32_srcs wgl/dm-wgl.c wgl/if_wgl.c)
   set(DM_EXTRA_LIBS ${DM_EXTRA_LIBS} ${OPENGL_LIBRARIES})
-  set_property(SOURCE dm-wgl.c APPEND PROPERTY COMPILE_DEFINITIONS 
FB_USE_INTERNAL_API)
-  set_property(SOURCE if_wgl.c APPEND PROPERTY COMPILE_DEFINITIONS 
FB_USE_INTERNAL_API)
+  set_property(SOURCE wgl/dm-wgl.c APPEND PROPERTY COMPILE_DEFINITIONS 
FB_USE_INTERNAL_API)
+  set_property(SOURCE wgl/if_wgl.c APPEND PROPERTY COMPILE_DEFINITIONS 
FB_USE_INTERNAL_API)
 endif(WIN32 AND BRLCAD_ENABLE_OPENGL)
 
 if(BRLCAD_ENABLE_X11)
@@ -41,26 +41,26 @@
 
 if(BRLCAD_ENABLE_X11 AND BRLCAD_ENABLE_TK)
   list(APPEND libdm_DEFINES DM_X IF_X)
-  set(dmx11_srcs dm-X.c if_X24.c)
+  set(dmx11_srcs X/dm-X.c X/if_X24.c)
   set(DM_EXTRA_LIBS ${DM_EXTRA_LIBS} ${X11_LIBRARIES})
-  set_property(SOURCE dm-X.c APPEND PROPERTY COMPILE_DEFINITIONS 
FB_USE_INTERNAL_API)
-  set_property(SOURCE if_X24.c APPEND PROPERTY COMPILE_DEFINITIONS 
FB_USE_INTERNAL_API)
+  set_property(SOURCE X/dm-X.c APPEND PROPERTY COMPILE_DEFINITIONS 
FB_USE_INTERNAL_API)
+  set_property(SOURCE X/if_X24.c APPEND PROPERTY COMPILE_DEFINITIONS 
FB_USE_INTERNAL_API)
 endif(BRLCAD_ENABLE_X11 AND BRLCAD_ENABLE_TK)
 
 if(BRLCAD_ENABLE_X11 AND BRLCAD_ENABLE_OPENGL AND BRLCAD_ENABLE_TK)
   list(APPEND libdm_DEFINES DM_OGL IF_OGL)
-  set(dmogl_srcs dm-ogl.c if_ogl.c)
+  set(dmogl_srcs glx/dm-ogl.c glx/if_ogl.c)
   set(DM_EXTRA_LIBS ${DM_EXTRA_LIBS} ${OPENGL_LIBRARIES})
-  set_property(SOURCE dm-ogl.c APPEND PROPERTY COMPILE_DEFINITIONS 
FB_USE_INTERNAL_API)
-  set_property(SOURCE if_ogl.c APPEND PROPERTY COMPILE_DEFINITIONS 
FB_USE_INTERNAL_API)
+  set_property(SOURCE glx/dm-ogl.c APPEND PROPERTY COMPILE_DEFINITIONS 
FB_USE_INTERNAL_API)
+  set_property(SOURCE glx/if_ogl.c APPEND PROPERTY COMPILE_DEFINITIONS 
FB_USE_INTERNAL_API)
 endif(BRLCAD_ENABLE_X11 AND BRLCAD_ENABLE_OPENGL AND BRLCAD_ENABLE_TK)
 
 if(BRLCAD_ENABLE_TK AND NOT WIN32)
   list(APPEND libdm_DEFINES DM_TK IF_TK)
   set(DM_EXTRA_LIBS ${DM_EXTRA_LIBS} ${TCL_LIBRARY} ${TK_LIBRARY})
-  set(dmtk_srcs dm-tk.c if_tk.c)
-  set_property(SOURCE dm-tk.c APPEND PROPERTY COMPILE_DEFINITIONS 
FB_USE_INTERNAL_API)
-  set_property(SOURCE if_tk.c APPEND PROPERTY COMPILE_DEFINITIONS 
FB_USE_INTERNAL_API)
+  set(dmtk_srcs tk/dm-tk.c tk/if_tk.c)
+  set_property(SOURCE tk/dm-tk.c APPEND PROPERTY COMPILE_DEFINITIONS 
FB_USE_INTERNAL_API)
+  set_property(SOURCE tk/if_tk.c APPEND PROPERTY COMPILE_DEFINITIONS 
FB_USE_INTERNAL_API)
 endif(BRLCAD_ENABLE_TK AND NOT WIN32)
 
 if(BRLCAD_ENABLE_QT)
@@ -67,9 +67,9 @@
   CHECK_CXX_FLAG(Wno-float-equal)
 
   list(APPEND libdm_DEFINES DM_QT IF_QT)
-  set(dmqt_srcs dm-qt.cpp if_qt.cpp)
-  set_property(SOURCE dm-qt.cpp APPEND PROPERTY COMPILE_DEFINITIONS 
FB_USE_INTERNAL_API)
-  set_property(SOURCE if_qt.cpp APPEND PROPERTY COMPILE_DEFINITIONS 
FB_USE_INTERNAL_API)
+  set(dmqt_srcs qt/dm-qt.cpp qt/if_qt.cpp)
+  set_property(SOURCE qt/dm-qt.cpp APPEND PROPERTY COMPILE_DEFINITIONS 
FB_USE_INTERNAL_API)
+  set_property(SOURCE qt/if_qt.cpp APPEND PROPERTY COMPILE_DEFINITIONS 
FB_USE_INTERNAL_API)
   set(CMAKE_AUTOMOC ON)
   set(CMAKE_INCLUDE_CURRENT_DIR ON)
   add_definitions(${Qt5Widgets_DEFINITIONS})
@@ -82,9 +82,9 @@
   )
 if(BRLCAD_ENABLE_OSG AND BRLCAD_ENABLE_TK)
   list(APPEND libdm_DEFINES DM_OSGL IF_OSGL)
-  set(dmosg_srcs dm-osgl.cpp if_osgl.cpp)
-  set_property(SOURCE dm-osgl.cpp APPEND PROPERTY COMPILE_DEFINITIONS 
FB_USE_INTERNAL_API)
-  set_property(SOURCE if_osgl.cpp APPEND PROPERTY COMPILE_DEFINITIONS 
FB_USE_INTERNAL_API)
+  set(dmosg_srcs osgl/dm-osgl.cpp osgl/if_osgl.cpp)
+  set_property(SOURCE osgl/dm-osgl.cpp APPEND PROPERTY COMPILE_DEFINITIONS 
FB_USE_INTERNAL_API)
+  set_property(SOURCE osgl/if_osgl.cpp APPEND PROPERTY COMPILE_DEFINITIONS 
FB_USE_INTERNAL_API)
   set(OSG_LIBRARIES
     ${OPENGL_LIBRARIES}
     ${OSG_LIBRARY}
@@ -104,26 +104,20 @@
   ${dmosg_srcs}
   ${dmtk_srcs}
   ${dmqt_srcs}
+  null/dm-Null.c
+  null/if_null.c
+  plot/dm-plot.c
+  postscript/dm-ps.c
+  txt/dm-txt.c
+  txt/if_debug.c
   adc.c
+  asize.c
   axes.c
   clip.c
   color.c
-  dm-Null.c
   dm-generic.c
-  dm-plot.c
-  dm-ps.c
   dm_obj.c
   dm_util.c
-  dm-txt.c
-  grid.c
-  knob.c
-  labels.c
-  options.c
-  query.c
-  rect.c
-  scale.c
-
-  asize.c
   fb_generic.c
   fb_log.c
   fb_obj.c
@@ -131,13 +125,17 @@
   fb_rect.c
   fb_util.c
   fbserv_obj.c
-  if_debug.c
+  grid.c
   if_disk.c
   if_mem.c
-  if_null.c
   if_remote.c
   if_stack.c
-
+  knob.c
+  labels.c
+  options.c
+  query.c
+  rect.c
+  scale.c
   tcl.c
   vers.c
   )
@@ -163,40 +161,40 @@
   CMakeLists.txt
   README
   TODO
-  dm-Null.h
-  dm-X.c
-  dm-X.h
-  dm-glx.h
-  dm-ogl.c
-  dm-ogl.h
-  dm-osgl.cpp
-  dm-osgl.h
-  dm-plot.h
-  dm-ps.h
-  dm-qt.cpp
-  dm-qt.h
-  dm-tk.c
-  dm-tk.h
-  dm-wgl.c
-  dm-wgl.h
+  X/dm-X.c
+  X/dm-X.h
+  X/if_X24.c
   dm_private.h
   dm_xvars.h
-  if_TEMPLATE.c
-  if_X24.c
-  if_ogl.c
-  if_osgl.cpp
-  if_qt.cpp
-  if_tk.c
-  if_wgl.c
   fb_private.h
-  osg_fb_manipulator.h
   fontstash/LICENSE.fontstash
   fontstash/README.md
   fontstash/fontstash.h
   fontstash/glfontstash.h
   fontstash/stb_truetype.h
-  osg-test.cpp
-  osg_bob.cpp
+  glx/dm-glx.h
+  glx/dm-ogl.c
+  glx/dm-ogl.h
+  glx/if_ogl.c
+  if_TEMPLATE.c
+  null/dm-Null.h
+  osgl/dm-osgl.cpp
+  osgl/dm-osgl.h
+  osgl/if_osgl.cpp
+  osgl/osg-test.cpp
+  osgl/osg_bob.cpp
+  osgl/osg_fb_manipulator.h
+  plot/dm-plot.h
+  postscript/dm-ps.h
+  qt/dm-qt.cpp
+  qt/dm-qt.h
+  qt/if_qt.cpp
+  tk/dm-tk.c
+  tk/dm-tk.h
+  tk/if_tk.c
+  wgl/dm-wgl.c
+  wgl/dm-wgl.h
+  wgl/if_wgl.c
   )
 CMAKEFILES(${libdm_ignore_files})
 CMAKEFILES(dm_private.h)

Copied: brlcad/branches/dm-fb-merge/src/libdm/X/dm-X.c (from rev 75426, 
brlcad/branches/dm-fb-merge/src/libdm/dm-X.c)
===================================================================
--- brlcad/branches/dm-fb-merge/src/libdm/X/dm-X.c                              
(rev 0)
+++ brlcad/branches/dm-fb-merge/src/libdm/X/dm-X.c      2020-04-16 21:11:44 UTC 
(rev 75427)
@@ -0,0 +1,1819 @@
+/*                          D M - X . C
+ * BRL-CAD
+ *
+ * Copyright (c) 1988-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.
+ */
+/** @file libdm/dm-X.c
+ *
+ * An X Window System Display Manager.
+ *
+ */
+
+#include "common.h"
+
+#ifdef DM_X
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#include <string.h>
+#include <math.h>
+
+#define class REDEFINE_CLASS_STRING_TO_AVOID_CXX_CONFLICT
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#ifdef HAVE_X11_XOSDEFS_H
+#  include <X11/Xfuncproto.h>
+#  include <X11/Xosdefs.h>
+#endif
+
+#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
+#  include <X11/extensions/XInput.h>
+#endif /* HAVE_X11_XINPUT_H */
+
+#if defined(linux)
+#  undef X_NOT_STDC_ENV
+#  undef X_NOT_POSIX
+#endif
+
+#ifdef HAVE_TK
+#  include "tk.h"
+#endif
+
+#include "vmath.h"
+#include "bu/endian.h"
+#include "bn.h"
+#include "dm.h"
+#include "dm-X.h"
+#include "dm-Null.h"
+#include "./dm_xvars.h"
+#include "dm.h"
+#include "./fb_X.h"
+
+#include "rt/solid.h"
+
+#include "dm_private.h"
+
+#define PLOTBOUND 1000.0       /* Max magnification in Rot matrix */
+
+#define DM_X_DEFAULT_POINT_SIZE 1.0
+
+extern void X_allocate_color_cube(Display *, Colormap, long unsigned int *, 
int, int, int);
+extern unsigned long X_get_pixel(unsigned char, unsigned char, unsigned char, 
long unsigned int *, int);
+
+
+struct allocated_colors {
+    struct bu_list l;
+    int r;
+    int g;
+    int b;
+    XColor c;
+};
+
+
+HIDDEN void
+get_color(Display *dpy, Colormap cmap, XColor *color)
+{
+    Status st;
+    static struct allocated_colors *colors = NULL;
+    struct allocated_colors *c;
+    int r, g, b;
+
+    if (!colors) {
+       BU_ALLOC(colors, struct allocated_colors);
+       BU_LIST_INIT(&(colors->l));
+       colors->r = colors->g = colors->b = -1;
+    }
+
+    /* allocated colors are stashed into a list in order to avoid
+     * subsequent repeat allocations.
+     */
+    for (BU_LIST_FOR(c, allocated_colors, &(colors->l))) {
+       if (DM_SAME_COLOR(c->r, c->g, c->b, color->red, color->green, 
color->blue)) {
+           *color = c->c; /* struct copy */
+           return;
+       }
+    }
+
+    r = color->red;
+    g = color->green;
+    b = color->blue;
+
+    st = XAllocColor(dpy, cmap, color);
+    switch (st) {
+       case 1:
+           break;
+       case BadColor:
+           bu_log("XAllocColor failed (BadColor) for (%3d, %3d, %3d) %04x, 
%04x, %04x\n",
+                  (r >> 8), (g >> 8), (b >> 8),
+                  r, g, b);
+           break;
+
+       default:
+           bu_log("XAllocColor error for (%3d, %3d, %3d) %04x, %04x, %04x\n",
+                  (r >> 8), (g >> 8), (b >> 8),
+                  r, g, b);
+           break;
+    }
+
+    /* got new valid color, add it to our list */
+    BU_ALLOC(c, struct allocated_colors);
+    c->r = r;
+    c->g = g;
+    c->b = b;
+    c->c = *color; /* struct copy */
+    BU_LIST_PUSH(&(colors->l), &(c->l));
+}
+
+
+HIDDEN int
+X_reshape(struct dm *dmp, int width, int height)
+{
+    struct x_vars *privars = (struct x_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;
+
+    privars->disp_mat[0] = 2. * privars->ppmm_x / dmp->i->dm_width;
+    privars->disp_mat[5] = 2. * privars->ppmm_y / dmp->i->dm_width;
+
+    return 0;
+}
+
+
+HIDDEN int
+X_configureWin_guts(struct dm *dmp, int force)
+{
+    XWindowAttributes xwa;
+    XFontStruct *newfontstruct;
+    XGCValues gcv;
+    struct dm_xvars *pubvars = (struct dm_xvars *)dmp->i->dm_vars.pub_vars;
+    struct x_vars *privars = (struct x_vars *)dmp->i->dm_vars.priv_vars;
+
+    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;
+
+    X_reshape(dmp, xwa.width, xwa.height);
+
+    if (dmp->i->dm_debugLevel) {
+       bu_log("X_configureWin_guts()\n");
+       bu_log("width = %d, height = %d\n", dmp->i->dm_width, 
dmp->i->dm_height);
+    }
+
+#ifdef HAVE_TK
+    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));
+#endif
+
+    /* 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("dm-X: Can't open font '%s' or '%s'\n", FONT9, FONTBACK);
+               return BRLCAD_ERROR;
+           }
+       }
+
+       gcv.font = pubvars->fontstruct->fid;
+       XChangeGC(pubvars->dpy,
+                 privars->gc, GCFont, &gcv);
+    }
+
+    /* 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;
+               gcv.font = pubvars->fontstruct->fid;
+               XChangeGC(pubvars->dpy,
+                         privars->gc, GCFont, &gcv);
+           }
+       }
+    } 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;
+               gcv.font = pubvars->fontstruct->fid;
+               XChangeGC(pubvars->dpy,
+                         privars->gc, GCFont, &gcv);
+           }
+       }
+    } 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;
+               gcv.font = pubvars->fontstruct->fid;
+               XChangeGC(pubvars->dpy,
+                         privars->gc, GCFont, &gcv);
+           }
+       }
+    } 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;
+               gcv.font = pubvars->fontstruct->fid;
+               XChangeGC(pubvars->dpy,
+                         privars->gc, GCFont, &gcv);
+           }
+       }
+    } else {
+       if (pubvars->fontstruct->per_char->width != 9) {
+           if ((newfontstruct = XLoadQueryFont(pubvars->dpy,
+                                               FONT9)) != NULL) {
+               XFreeFont(pubvars->dpy,
+                         pubvars->fontstruct);
+               pubvars->fontstruct = newfontstruct;
+               gcv.font = pubvars->fontstruct->fid;
+               XChangeGC(pubvars->dpy,
+                         privars->gc, GCFont, &gcv);
+           }
+       }
+    }
+
+    return BRLCAD_OK;
+}
+
+
+HIDDEN XVisualInfo *
+X_choose_visual(struct dm *dmp)
+{
+    XVisualInfo *vip, vitemp, *vibase, *maxvip;
+    int num, i, j;
+    int tries, baddepth;
+    int desire_trueColor = 1;
+    int min_depth = 8;
+    int *good = NULL;
+    int screen;
+    struct dm_xvars *pubvars = (struct dm_xvars *)dmp->i->dm_vars.pub_vars;
+    struct x_vars *privars = (struct x_vars *)dmp->i->dm_vars.priv_vars;
+
+    vibase = XGetVisualInfo(pubvars->dpy, 0, &vitemp, &num);
+    screen = DefaultScreen(((struct dm_xvars *)dmp->i->dm_vars.pub_vars)->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;
+           if (vip->depth < min_depth)
+               continue;
+           if (desire_trueColor) {
+               if (vip->class != TrueColor)
+                   continue;
+           } else if (vip->class != PseudoColor)
+               continue;
+
+           /* this visual meets criteria */
+           good[j++] = i;
+       }
+
+       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;
+               }
+           }
+
+           /* make sure Tk handles it */
+           if (desire_trueColor) {
+               pubvars->cmap =
+                   XCreateColormap(pubvars->dpy,
+                                   RootWindow(pubvars->dpy,
+                                              maxvip->screen),
+                                   maxvip->visual, AllocNone);
+               privars->is_trueColor = 1;
+           } else {
+               pubvars->cmap =
+                   XCreateColormap(pubvars->dpy,
+                                   RootWindow(pubvars->dpy,
+                                              maxvip->screen),
+                                   maxvip->visual, AllocAll);
+               privars->is_trueColor = 0;
+           }
+
+#ifdef HAVE_TK
+           if (Tk_SetWindowVisual(pubvars->xtkwin,
+                                  maxvip->visual,
+                                  maxvip->depth,
+                                  pubvars->cmap)) {
+               pubvars->depth = maxvip->depth;
+
+               bu_free(good, "dealloc good visuals");
+               return maxvip; /* success */
+           } else
+#endif
+           {
+               /* retry with lesser depth */
+               baddepth = maxvip->depth;
+               XFreeColormap(pubvars->dpy, pubvars->cmap);
+           }
+       }
+
+       if (desire_trueColor) {
+           desire_trueColor = 0;
+       } else {
+           /* ran out of visuals, give up */
+           break;
+       }
+    }
+
+    bu_free(good, "dealloc good visuals");
+    return (XVisualInfo *)NULL; /* failure */
+}
+
+
+/*
+ * Gracefully release the display.
+ */
+HIDDEN int
+X_close(struct dm *dmp)
+{
+    struct dm_xvars *pubvars = (struct dm_xvars *)dmp->i->dm_vars.pub_vars;
+    struct x_vars *privars = (struct x_vars *)dmp->i->dm_vars.priv_vars;
+
+    if (pubvars->dpy) {
+       if (privars->gc)
+           XFreeGC(pubvars->dpy,
+                   privars->gc);
+
+#ifdef HAVE_TK
+       if (privars->pix)
+           Tk_FreePixmap(pubvars->dpy,
+                         privars->pix);
+#endif
+
+       /*XXX Possibly need to free the colormap */
+       if (pubvars->cmap)
+           XFreeColormap(pubvars->dpy,
+                         pubvars->cmap);
+
+#ifdef HAVE_TK
+       if (pubvars->xtkwin)
+           Tk_DestroyWindow(pubvars->xtkwin);
+#endif
+
+    }
+
+    bu_vls_free(&dmp->i->dm_pathName);
+    bu_vls_free(&dmp->i->dm_tkName);
+    bu_vls_free(&dmp->i->dm_dName);
+    bu_free((void *)dmp->i->dm_vars.priv_vars, "X_close: x_vars");
+    bu_free((void *)dmp->i->dm_vars.pub_vars, "X_close: dm_xvars");
+    bu_free((void *)dmp->i, "X_close: dmp->i");
+    bu_free((void *)dmp, "X_close: dmp");
+
+    return BRLCAD_OK;
+}
+
+
+/*
+ * Fire up the display manager, and the display processor.
+ *
+ */
+struct dm *
+X_open_dm(Tcl_Interp *interp, int argc, char **argv)
+{
+    static int count = 0;
+    int make_square = -1;
+    XGCValues gcv;
+#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 = NULL;
+#endif
+    struct bu_vls str = BU_VLS_INIT_ZERO;
+    struct bu_vls init_proc_vls = BU_VLS_INIT_ZERO;
+    struct dm *dmp = NULL;
+    struct dm_impl *dmpi = NULL;
+    Tk_Window tkwin = (Tk_Window)NULL;
+    Screen *screen = (Screen *)NULL;
+
+    struct dm_xvars *pubvars = NULL;
+    struct x_vars *privars = NULL;
+
+#ifdef HAVE_TK
+    if ((tkwin = Tk_MainWindow(interp)) == NULL) {
+       return DM_NULL;
+    }
+#endif
+
+    BU_ALLOC(dmp, struct dm);
+    BU_ALLOC(dmpi, struct dm_impl);
+
+    *dmpi = *dm_X.i; /* struct copy */
+    dmp->i = dmpi;
+    dmp->i->dm_interp = interp;
+
+    BU_ALLOC(dmp->i->dm_vars.pub_vars, struct dm_xvars);
+    pubvars = (struct dm_xvars *)dmp->i->dm_vars.pub_vars;
+
+    BU_ALLOC(dmp->i->dm_vars.priv_vars, struct x_vars);
+    privars = (struct x_vars *)dmp->i->dm_vars.priv_vars;
+
+    bu_vls_init(&dmp->i->dm_pathName);
+    bu_vls_init(&dmp->i->dm_tkName);
+    bu_vls_init(&dmp->i->dm_dName);
+
+    dm_processOptions(dmp, &init_proc_vls, --argc, ++argv);
+
+    if (bu_vls_strlen(&dmp->i->dm_pathName) == 0)
+       bu_vls_printf(&dmp->i->dm_pathName, ".dm_X%d", count);
+
+    ++count;
+    if (bu_vls_strlen(&dmp->i->dm_dName) == 0) {
+       char *dp;
+
+       dp = getenv("DISPLAY");
+       if (dp)
+           bu_vls_strcpy(&dmp->i->dm_dName, dp);
+       else
+           bu_vls_strcpy(&dmp->i->dm_dName, ":0.0");
+    }
+    if (bu_vls_strlen(&init_proc_vls) == 0)
+       bu_vls_strcpy(&init_proc_vls, "bind_dm");
+
+    /* initialize dm specific variables */
+    pubvars->devmotionnotify = LASTEvent;
+    pubvars->devbuttonpress = LASTEvent;
+    pubvars->devbuttonrelease = LASTEvent;
+    dmp->i->dm_aspect = 1.0;
+
+    pubvars->fontstruct = NULL;
+
+    if (dmp->i->dm_top) {
+#ifdef HAVE_TK
+       /* 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->top = pubvars->xtkwin;
+#endif
+    } else {
+       char *cp;
+
+       cp = strrchr(bu_vls_addr(&dmp->i->dm_pathName), (int)'.');
+       if (cp == bu_vls_addr(&dmp->i->dm_pathName)) {
+           pubvars->top = tkwin;
+       } else {
+           struct bu_vls top_vls = BU_VLS_INIT_ZERO;
+
+           bu_vls_strncpy(&top_vls, (const char 
*)bu_vls_addr(&dmp->i->dm_pathName), cp - bu_vls_addr(&dmp->i->dm_pathName));
+
+#ifdef HAVE_TK
+           pubvars->top =
+               Tk_NameToWindow(interp, bu_vls_addr(&top_vls), tkwin);
+#endif
+           bu_vls_free(&top_vls);
+       }
+
+#ifdef HAVE_TK
+       /* Make xtkwin an embedded window */
+       pubvars->xtkwin =
+           Tk_CreateWindow(interp, pubvars->top,
+                           cp + 1, (char *)NULL);
+#endif
+    }
+
+    if (pubvars->xtkwin == NULL) {
+       bu_log("X_open_dm: Failed to open %s\n", 
bu_vls_addr(&dmp->i->dm_pathName));
+       (void)X_close(dmp);
+       return DM_NULL;
+    }
+
+#ifdef HAVE_TK
+    bu_vls_printf(&dmp->i->dm_tkName, "%s",
+                 (char *)Tk_Name(pubvars->xtkwin));
+#endif
+
+    bu_vls_printf(&str, "_init_dm %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(&str);
+       (void)X_close(dmp);
+       return DM_NULL;
+    }
+
+    bu_vls_free(&init_proc_vls);
+    bu_vls_free(&str);
+
+    pubvars->dpy = NULL;
+#ifdef HAVE_TK
+    pubvars->dpy = Tk_Display(pubvars->top);
+#endif
+
+    /* make sure there really is a display before proceeding. */
+    if (!pubvars->dpy) {
+       bu_log("ERROR: Unable to attach to display (%s)\n", 
bu_vls_addr(&dmp->i->dm_pathName));
+       (void)X_close(dmp);
+       return DM_NULL;
+    }
+
+    screen = DefaultScreenOfDisplay(pubvars->dpy);
+
+    if (!screen) {
+#ifdef HAVE_TK
+       /* failed to get a default screen, try harder */
+       screen = Tk_Screen(pubvars->top);
+#endif
+    }
+
+    /* make sure there really is a screen before processing. */
+    if (!screen) {
+       bu_log("ERROR: Unable to attach to screen (%s)\n", 
bu_vls_addr(&dmp->i->dm_pathName));
+       (void)X_close(dmp);
+       return DM_NULL;
+    }
+
+    /* FIXME: Applications on Mac OS X linking against the system
+     * Tcl/Tk frameworks may crash here due to dpy being a high (7+
+     * digit) value and the screens[] array it indexes into being 0x0.
+     * Might have better luck calling functions instead of macros.
+     */
+
+    privars->ppmm_x = screen->width / screen->mwidth;
+    privars->ppmm_y = screen->height / screen->mheight;
+
+    if (dmp->i->dm_width == 0) {
+       dmp->i->dm_width =
+           DisplayWidth(pubvars->dpy,
+                        DefaultScreen(pubvars->dpy)) - 30;
+       ++make_square;
+    }
+
+    if (dmp->i->dm_height == 0) {
+       dmp->i->dm_height =
+           DisplayHeight(pubvars->dpy,
+                         DefaultScreen(pubvars->dpy)) - 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;
+    }
+
+#ifdef HAVE_TK
+    Tk_GeometryRequest(pubvars->xtkwin,
+                      dmp->i->dm_width,
+                      dmp->i->dm_height);
+#endif
+
+    /* must do this before MakeExist */
+    if ((pubvars->vip = X_choose_visual(dmp)) == NULL) {
+       bu_log("X_open_dm: Can't get an appropriate visual.\n");
+       (void)X_close(dmp);
+       return DM_NULL;
+    }
+
+#ifdef HAVE_TK
+    Tk_MakeWindowExist(pubvars->xtkwin);
+    pubvars->win = Tk_WindowId(pubvars->xtkwin);
+    dmp->i->dm_id = pubvars->win;
+    privars->pix =
+       Tk_GetPixmap(pubvars->dpy,
+                    pubvars->win,
+                    dmp->i->dm_width,
+                    dmp->i->dm_height,
+                    Tk_Depth(pubvars->xtkwin));
+#endif
+
+    if (privars->is_trueColor) {
+       XColor fg, bg;
+
+       INIT_XCOLOR(&fg);
+       INIT_XCOLOR(&bg);
+
+       fg.red = 65535;
+       fg.green = fg.blue = 0;
+
+       get_color(pubvars->dpy,
+                 pubvars->cmap,
+                 &fg);
+
+       privars->fg = fg.pixel;
+
+       bg.red = bg.green = bg.blue = 0;
+       get_color(pubvars->dpy,
+                 pubvars->cmap,
+                 &bg);
+
+       privars->bg = bg.pixel;
+    } else {
+       X_allocate_color_cube(pubvars->dpy,
+                             pubvars->cmap,
+                             privars->pixels,
+                             /* cube dimension, uses XStoreColor */
+                             6, CMAP_BASE, 1);
+
+       privars->bg =
+           X_get_pixel(DM_BLACK,
+                       privars->pixels,
+                       CUBE_DIMENSION);
+       privars->fg =
+           X_get_pixel(DM_RED,
+                       privars->pixels,
+                       CUBE_DIMENSION);
+    }
+
+    gcv.background = privars->bg;
+    gcv.foreground = privars->fg;
+    privars->gc = XCreateGC(pubvars->dpy,
+                           pubvars->win,
+                           (GCForeground|GCBackground), &gcv);
+
+    /* First see if the server supports XInputExtension */
+    {
+       int return_val;
+
+       if (!XQueryExtension(pubvars->dpy,
+                            "XInputExtension", &return_val, &return_val, 
&return_val))
+           goto Skip_dials;
+    }
+
+#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);
+    }
+
+    if (list == (XDeviceInfoPtr)NULL ||
+       list == (XDeviceInfoPtr)1) goto Done;
+
+    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("X_open_dm: Couldn't open the dials+buttons\n");
+                   goto Done;
+               }
+
+               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;
+                   }
+               }
+
+               XSelectExtensionEvent(pubvars->dpy,
+                                     pubvars->win, e_class, nclass);
+               goto Done;
+           }
+       }
+    }
+Done:
+    XFreeDeviceList(olist);
+#endif
+
+Skip_dials:
+    MAT_IDN(privars->mod_mat);
+    MAT_IDN(privars->disp_mat);
+
+    privars->xmat = &(privars->mod_mat[0]);
+
+    (void)X_configureWin_guts(dmp, 1);
+
+#ifdef HAVE_TK
+    Tk_SetWindowBackground(pubvars->xtkwin,
+                          privars->bg);
+    Tk_MapWindow(pubvars->xtkwin);
+#endif
+
+    return dmp;
+}
+
+
+HIDDEN int
+X_drawBegin(struct dm *dmp)
+{
+    XGCValues gcv;
+    struct dm_xvars *pubvars = (struct dm_xvars *)dmp->i->dm_vars.pub_vars;
+    struct x_vars *privars = (struct x_vars *)dmp->i->dm_vars.priv_vars;
+
+    if (dmp->i->dm_debugLevel)
+       bu_log("X_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);
+
+    /* reset foreground */
+    gcv.foreground = privars->fg;
+    XChangeGC(pubvars->dpy,
+             privars->gc,
+             GCForeground, &gcv);
+
+    return BRLCAD_OK;
+}
+
+
+HIDDEN int
+X_drawEnd(struct dm *dmp)
+{
+    struct dm_xvars *pubvars = (struct dm_xvars *)dmp->i->dm_vars.pub_vars;
+    struct x_vars *privars = (struct x_vars *)dmp->i->dm_vars.priv_vars;
+
+    if (dmp->i->dm_debugLevel)
+       bu_log("X_drawEnd()\n");
+
+    XCopyArea(pubvars->dpy,
+             privars->pix,
+             pubvars->win,
+             privars->gc,
+             0, 0, dmp->i->dm_width,
+             dmp->i->dm_height, 0, 0);
+
+    /* Prevent lag between events and updates */
+    XSync(pubvars->dpy, 0);
+
+    return BRLCAD_OK;
+}
+
+
+/*
+ * Load a new Model matrix.  This will be followed by many
+ * calls to X_draw().
+ */
+HIDDEN int
+X_loadMatrix(struct dm *dmp, fastf_t *mat, int which_eye)
+{
+    struct x_vars *privars = (struct x_vars *)dmp->i->dm_vars.priv_vars;
+
+    if (dmp->i->dm_debugLevel) {
+       bu_log("X_load_Matrix()\n");
+
+       bu_log("which eye = %d\t", which_eye);
+       bu_log("transformation matrix = \n");
+
+       /* note the row/column ordering */
+       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]);
+    }
+
+    MAT_COPY(privars->mod_mat, mat);
+    return BRLCAD_OK;
+}
+
+
+HIDDEN int
+X_drawVList(struct dm *dmp, struct bn_vlist *vp)
+{
+    extern int vectorThreshold;        /* defined in libdm/tcl.c */
+
+    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;
+    fastf_t dist_prev=1.0;
+    fastf_t pointSize = DM_X_DEFAULT_POINT_SIZE;
+
+    static int nvectors = 0;
+    struct dm_xvars *pubvars = (struct dm_xvars *)dmp->i->dm_vars.pub_vars;
+    struct x_vars *privars = (struct x_vars *)dmp->i->dm_vars.priv_vars;
+
+    /* 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;
+
+    nseg = 0;
+    segp = segbuf;
+    for (BU_LIST_FOR(tvp, bn_vlist, &vp->l)) {
+       int i;
+       int nused = tvp->nused;
+       int *cmd = tvp->cmd;
+       point_t *pt = tvp->pt;
+       point_t tlate;
+       fastf_t dist;
+
+       /* 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_POLY_START:
+               case BN_VLIST_POLY_VERTNORM:
+               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:
+               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));
+                   }
+
+                   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);
+                   }
+
+                   lpnt[0] *= 2047;
+                   lpnt[1] *= 2047 * dmp->i->dm_aspect;
+                   lpnt[2] *= 2047;
+                   continue;
+               case BN_VLIST_POLY_DRAW:
+               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));
+                   }
+
+                   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;
+
+                               /* 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;
+
+                               /* clip other end */
+                               VSUB2(diff, *pt, *pt_prev);
+                               alpha = (-dist_prev + delta) / (dist - 
dist_prev);
+                               VJOIN1(tmp_pt, *pt_prev, alpha, diff);
+                               MAT4X3PNT(lpnt, 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);
+                   }
+
+                   pnt[0] *= 2047;
+                   pnt[1] *= 2047 * dmp->i->dm_aspect;
+                   pnt[2] *= 2047;
+
+                   /* save pnt --- it might get changed by clip() */
+                   VMOVE(spnt, pnt);
+                   pt_prev = pt;
+
+                   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]);
+                   }
+
+                   if (dmp->i->dm_zclip) {
+                       if (vclip(lpnt, pnt,
+                                 dmp->i->dm_clipmin,
+                                 dmp->i->dm_clipmax) == 0) {
+                           VMOVE(lpnt, spnt);
+                           continue;
+                       }
+                   } else {
+                       fastf_t min_short = (fastf_t)SHRT_MIN;
+                       fastf_t max_short = (fastf_t)SHRT_MAX;
+
+                       /* 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;
+                           }
+                       }
+                   }
+
+                   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]);
+                   }
+
+                   /* 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]);
+
+                   nseg++;
+                   segp++;
+                   VMOVE(lpnt, spnt);
+
+                   if (nseg == 1024) {
+                       XDrawSegments(pubvars->dpy,
+                                     privars->pix,
+                                     privars->gc, segbuf, nseg);
+
+                       nseg = 0;
+                       segp = segbuf;
+                   }
+                   break;
+               case BN_VLIST_POINT_DRAW:
+                   if (dmp->i->dm_debugLevel > 2) {
+                       bu_log("before transformation:\n");
+                       bu_log("pt - %lf %lf %lf\n", V3ARGS(*pt));
+                   }
+
+                   if (dmp->i->dm_perspective > 0) {
+                       dist = VDOT(*pt, &(privars->xmat)[12]) + 
privars->xmat[15];
+
+                       if (dist <= 0.0) {
+                           /* nothing to plot - point is behind eye plane */
+                           continue;
+                       }
+                   }
+
+                   MAT4X3PNT(pnt, privars->xmat, *pt);
+
+                   pnt[0] *= 2047;
+                   pnt[1] *= 2047 * dmp->i->dm_aspect;
+                   pnt[2] *= 2047;
+                   VMOVE(lpnt, pnt);
+
+                   if (dmp->i->dm_debugLevel > 2) {
+                       bu_log("after clipping:\n");
+                       bu_log("pt - %lf %lf %lf\n", pnt[X], pnt[Y], pnt[Z]);
+                   }
+
+                   if (pointSize <= DM_X_DEFAULT_POINT_SIZE) {
+                       /* draws a single pixel */
+                       XDrawPoint(pubvars->dpy, privars->pix, privars->gc,
+                               GED_TO_Xx(dmp, pnt[0]), GED_TO_Xy(dmp, pnt[1]));
+                   } else {
+                       int upperLeft[2];
+
+                       /* need the upper-left adjusted a half-pixel
+                        * so points with odd size are centered.
+                        */
+                       upperLeft[X] = (double)GED_TO_Xx(dmp, pnt[0]) - 
(pointSize / 2.0) + 0.5;
+                       upperLeft[Y] = (double)GED_TO_Xy(dmp, pnt[1]) - 
(pointSize / 2.0) + 0.5;
+
+                       /* NOTE: in order to get smooth circles,
+                        * especially for small radii, X11 requires
+                        * that you draw both the interior and the
+                        * exterior.  only filling small radius
+                        * circles will otherwise render as a square.
+                        */
+                       XDrawArc(pubvars->dpy, privars->pix, privars->gc, 
upperLeft[X], upperLeft[Y], pointSize, pointSize, 0, 360*64);
+                       XFillArc(pubvars->dpy, privars->pix, privars->gc, 
upperLeft[X], upperLeft[Y], pointSize, pointSize, 0, 360*64);
+                   }
+                   break;
+               case BN_VLIST_POINT_SIZE:
+                   pointSize = (*pt)[0];
+                   if (pointSize < DM_X_DEFAULT_POINT_SIZE) {
+                       pointSize = DM_X_DEFAULT_POINT_SIZE;
+                   }
+                   break;
+           }
+       }
+
+       nvectors += nused;
+       if (nvectors >= vectorThreshold) {
+           if (dmp->i->dm_debugLevel)
+               bu_log("X_drawVList(): handle Tcl events\n");
+
+           nvectors = 0;
+
+           /* Handle events in the queue */
+           while (Tcl_DoOneEvent(TCL_ALL_EVENTS|TCL_DONT_WAIT));
+       }
+    }
+
+    if (nseg) {
+       XDrawSegments(pubvars->dpy,
+                     privars->pix,
+                     privars->gc, segbuf, nseg);
+    }
+
+    return BRLCAD_OK;
+}
+
+
+HIDDEN int
+X_draw(struct dm *dmp, struct bn_vlist *(*callback_function)(void *), void 
**data)
+{
+    struct bn_vlist *vp;
+    if (!callback_function) {
+       if (data) {
+           vp = (struct bn_vlist *)data;
+           X_drawVList(dmp, vp);
+       }
+    } else {
+       if (!data) {
+           return BRLCAD_ERROR;
+       } else {
+           (void)callback_function(data);
+       }
+    }
+    return BRLCAD_OK;
+}
+
+
+/**
+ * Restore the display processor to a normal mode of operation (i.e.,
+ * not scaled, rotated, displaced, etc.).
+ */
+HIDDEN int
+X_normal(struct dm *dmp)
+{
+    if (dmp->i->dm_debugLevel)
+       bu_log("X_normal()\n");
+
+    return BRLCAD_OK;
+}
+
+
+/**
+ * Output a string into the displaylist.  The starting position of the
+ * beam is as specified.
+ */
+HIDDEN int
+X_drawString2D(struct dm *dmp, const char *str, fastf_t x, fastf_t y, int 
size, int use_aspect)
+{
+    int sx, sy;
+    struct dm_xvars *pubvars = (struct dm_xvars *)dmp->i->dm_vars.pub_vars;
+    struct x_vars *privars = (struct x_vars *)dmp->i->dm_vars.priv_vars;
+
+    if (dmp->i->dm_debugLevel) {
+       bu_log("X_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) {
+           bu_log("\tuse_aspect - %d\t\taspect ratio - %g\n", use_aspect, 
dmp->i->dm_aspect);
+       } else
+           bu_log("\tuse_aspect - 0");
+    }
+
+    sx = dm_Normal2Xx(dmp, x);
+    sy = dm_Normal2Xy(dmp, y, use_aspect);
+
+    XDrawString(pubvars->dpy,
+               privars->pix,
+               privars->gc,
+               sx, sy, str, strlen(str));
+
+    return BRLCAD_OK;
+}
+
+
+HIDDEN int
+X_drawLine2D(struct dm *dmp, fastf_t x_1, fastf_t y_1, fastf_t x_2, fastf_t 
y_2)
+{
+    int sx1, sy1, sx2, sy2;
+    struct dm_xvars *pubvars = (struct dm_xvars *)dmp->i->dm_vars.pub_vars;
+    struct x_vars *privars = (struct x_vars *)dmp->i->dm_vars.priv_vars;
+
+    sx1 = dm_Normal2Xx(dmp, x_1);
+    sx2 = dm_Normal2Xx(dmp, x_2);
+    sy1 = dm_Normal2Xy(dmp, y_1, 0);
+    sy2 = dm_Normal2Xy(dmp, y_2, 0);
+
+    if (dmp->i->dm_debugLevel) {
+       bu_log("X_drawLine2D()\n");
+       bu_log("x1 = %g, y1 = %g\n", x_1, y_1);
+       bu_log("x2 = %g, y2 = %g\n", x_2, y_2);
+       bu_log("sx1 = %d, sy1 = %d\n", sx1, sy1);
+       bu_log("sx2 = %d, sy2 = %d\n", sx2, sy2);
+    }
+
+    XDrawLine(pubvars->dpy,
+             privars->pix,
+             privars->gc,
+             sx1, sy1, sx2, sy2);
+
+    return BRLCAD_OK;
+}
+
+
+HIDDEN int
+X_drawLine3D(struct dm *dmp, point_t pt1, point_t pt2)
+{
+    return draw_Line3D(dmp, pt1, pt2);
+}
+
+
+HIDDEN int
+X_drawLines3D(struct dm *dmp, int npoints, point_t *points, int UNUSED(sflag))
+{
+    if (!dmp || npoints < 0 || !points)
+       return BRLCAD_ERROR;
+
+    return BRLCAD_OK;
+}
+
+
+HIDDEN int
+X_drawPoint2D(struct dm *dmp, fastf_t x, fastf_t y)
+{
+    int sx, sy;
+    struct dm_xvars *pubvars = (struct dm_xvars *)dmp->i->dm_vars.pub_vars;
+    struct x_vars *privars = (struct x_vars *)dmp->i->dm_vars.priv_vars;
+
+    sx = dm_Normal2Xx(dmp, x);
+    sy = dm_Normal2Xy(dmp, y, 0);
+
+    if (dmp->i->dm_debugLevel) {
+       bu_log("X_drawPoint2D()\n");
+       bu_log("x = %g, y = %g\n", x, y);
+       bu_log("sx = %d, sy = %d\n", sx, sy);
+    }
+
+    XDrawPoint(pubvars->dpy,
+              privars->pix,
+              privars->gc, sx, sy);
+
+    return BRLCAD_OK;
+}
+
+
+HIDDEN int
+X_setFGColor(struct dm *dmp, unsigned char r, unsigned char g, unsigned char 
b, int strict, fastf_t transparency)
+{
+    XGCValues gcv;
+    struct dm_xvars *pubvars = (struct dm_xvars *)dmp->i->dm_vars.pub_vars;
+    struct x_vars *privars = (struct x_vars *)dmp->i->dm_vars.priv_vars;
+
+    if (dmp->i->dm_debugLevel)
+       bu_log("X_setFGColor() rgb=[%d, %d, %d] strict=%d transparency=%f\n", 
r, g, b, strict, transparency);
+
+    dmp->i->dm_fg[0] = r;
+    dmp->i->dm_fg[1] = g;
+    dmp->i->dm_fg[2] = b;
+
+    if (privars->is_trueColor) {
+       XColor color;
+
+       INIT_XCOLOR(&color);
+
+       color.red = r << 8;
+       color.green = g << 8;
+       color.blue = b << 8;
+       get_color(pubvars->dpy,
+                 pubvars->cmap,
+                 &color);
+
+       gcv.foreground = color.pixel;
+    } else {
+       gcv.foreground = X_get_pixel(r, g, b, privars->pixels, CUBE_DIMENSION);
+    }
+
+    /* save foreground pixel */
+    privars->fg = gcv.foreground;
+
+    XChangeGC(pubvars->dpy,
+             privars->gc,
+             GCForeground, &gcv);
+
+    return BRLCAD_OK;
+}
+
+
+HIDDEN int
+X_setBGColor(struct dm *dmp, unsigned char r, unsigned char g, unsigned char b)
+{
+    struct dm_xvars *pubvars = (struct dm_xvars *)dmp->i->dm_vars.pub_vars;
+    struct x_vars *privars = (struct x_vars *)dmp->i->dm_vars.priv_vars;
+
+    if (dmp->i->dm_debugLevel)
+       bu_log("X_setBGColor()\n");
+
+    dmp->i->dm_bg[0] = r;
+    dmp->i->dm_bg[1] = g;
+    dmp->i->dm_bg[2] = b;
+
+    if (privars->is_trueColor) {
+       XColor color;
+
+       INIT_XCOLOR(&color);
+
+       color.red = r << 8;
+       color.green = g << 8;
+       color.blue = b << 8;
+
+       get_color(pubvars->dpy,
+                 pubvars->cmap,
+                 &color);
+
+       privars->bg = color.pixel;
+    } else
+       privars->bg =
+           X_get_pixel(r, g, b, privars->pixels, CUBE_DIMENSION);
+
+    return BRLCAD_OK;
+}
+
+
+HIDDEN int
+X_setLineAttr(struct dm *dmp, int width, int style)
+{
+    int linestyle;
+    struct dm_xvars *pubvars = (struct dm_xvars *)dmp->i->dm_vars.pub_vars;
+    struct x_vars *privars = (struct x_vars *)dmp->i->dm_vars.priv_vars;
+
+    if (dmp->i->dm_debugLevel)
+       bu_log("X_setLineAttr()\n");
+
+    dmp->i->dm_lineWidth = width;
+    dmp->i->dm_lineStyle = style;
+
+    if (width <= 1)
+       width = 0;
+
+    if (style == DM_DASHED_LINE)
+       linestyle = LineOnOffDash;
+    else
+       linestyle = LineSolid;
+
+    XSetLineAttributes(pubvars->dpy,
+                      privars->gc,
+                      width, linestyle, CapButt, JoinMiter);
+
+    return BRLCAD_OK;
+}
+
+
+HIDDEN int
+X_debug(struct dm *dmp, int lvl)
+{
+    dmp->i->dm_debugLevel = lvl;
+
+    return BRLCAD_OK;
+}
+
+
+HIDDEN int
+X_logfile(struct dm *dmp, const char *filename)
+{
+    bu_vls_sprintf(&dmp->i->dm_log, "%s", filename);
+
+    return BRLCAD_OK;
+}
+
+
+HIDDEN int
+X_setWinBounds(struct dm *dmp, fastf_t *w)
+{
+    if (dmp->i->dm_debugLevel)
+       bu_log("X_setWinBounds()\n");
+
+    dmp->i->dm_clipmin[0] = w[0];
+    dmp->i->dm_clipmin[1] = w[2];
+    dmp->i->dm_clipmin[2] = w[4];
+    dmp->i->dm_clipmax[0] = w[1];
+    dmp->i->dm_clipmax[1] = w[3];
+    dmp->i->dm_clipmax[2] = w[5];
+
+    return BRLCAD_OK;
+}
+
+
+HIDDEN int
+X_configureWin(struct dm *dmp, int force)
+{
+    /* don't force */
+    return X_configureWin_guts(dmp, force);
+}
+
+
+HIDDEN int
+X_setLight(struct dm *dmp, int light_on)
+{
+    if (dmp->i->dm_debugLevel)
+       bu_log("X_setLight:\n");
+
+    dmp->i->dm_light = light_on;
+
+    return BRLCAD_OK;
+}
+
+
+HIDDEN int
+X_setZBuffer(struct dm *dmp, int zbuffer_on)
+{
+    if (dmp->i->dm_debugLevel)
+       bu_log("X_setZBuffer:\n");
+
+    dmp->i->dm_zbuffer = zbuffer_on;
+
+    return BRLCAD_OK;
+}
+
+
+HIDDEN int
+X_getDisplayImage(struct dm *dmp, unsigned char **image)
+{
+    XImage *ximage_p;
+    unsigned char **rows;
+    unsigned char *idata;
+    unsigned char *irow;
+    int bytes_per_pixel;
+    int bytes_per_pixel_output = 3; /* limit for current bu_image raw pix 
usage */
+    int bytes_per_line_output;
+    int i, j, k;
+    unsigned char *dbyte0, *dbyte1, *dbyte2;
+    int red_shift;
+    int green_shift;
+    int blue_shift;
+    int red_bits;
+    int green_bits;
+    int blue_bits;
+
+
+    ximage_p = XGetImage(((struct dm_xvars *)dmp->i->dm_vars.pub_vars)->dpy,
+                        ((struct dm_xvars *)dmp->i->dm_vars.pub_vars)->win,
+                        0, 0,
+                        dmp->i->dm_width,
+                        dmp->i->dm_height,
+                        ~0, ZPixmap);
+
+    if (!ximage_p) {
+       bu_log("png: could not get XImage\n");
+       return BRLCAD_ERROR;
+    }
+
+    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 {
+       bu_log("png: %d bytes per pixel is not yet supported\n", 
bytes_per_pixel);
+       return BRLCAD_ERROR;
+    }
+
+    rows = (unsigned char **)bu_calloc(ximage_p->height, sizeof(unsigned char 
*), "rows");
+    idata = (unsigned char *)bu_calloc(ximage_p->height * ximage_p->width, 
bytes_per_pixel_output, "png data");
+    *image = idata;
+
+    /* for each scanline */
+    bytes_per_line_output = ximage_p->width * bytes_per_pixel_output;
+    for (i = ximage_p->height - 1, j = 0; 0 <= i; --i, ++j) {
+       /* irow points to the current scanline in ximage_p */
+       irow = (unsigned char *)(ximage_p->data + 
((ximage_p->height-i-1)*ximage_p->bytes_per_line));
+
+       if (bytes_per_pixel == 4) {
+           unsigned int pixel;
+
+           /* rows[j] points to the current scanline in idata */
+           rows[j] = (unsigned char *)(idata + 
((ximage_p->height-i-1)*bytes_per_line_output));
+
+           /* for each pixel in current scanline of ximage_p */
+           for (k = 0; k < ximage_p->width; k++) {
+               pixel = *((unsigned int *)(irow + k*bytes_per_pixel));
+
+               dbyte0 = rows[j] + k*bytes_per_pixel_output;
+               dbyte1 = dbyte0 + 1;
+               dbyte2 = dbyte0 + 2;
+
+               *dbyte0 = (pixel & ximage_p->red_mask) >> red_shift;
+               *dbyte1 = (pixel & ximage_p->green_mask) >> green_shift;
+               *dbyte2 = (pixel & ximage_p->blue_mask) >> blue_shift;
+           }
+       } else if (bytes_per_pixel == 2) {
+           unsigned short spixel;
+           unsigned long pixel;
+
+           /* rows[j] points to the current scanline in idata */
+           rows[j] = (unsigned char *)(idata + 
((ximage_p->height-i-1)*bytes_per_line_output));
+
+           /* for each pixel in current scanline of ximage_p */
+           for (k = 0; k < ximage_p->width; k++) {
+               spixel = *((unsigned short *)(irow + k*bytes_per_pixel));
+               pixel = spixel;
+
+               dbyte0 = rows[j] + k*bytes_per_pixel_output;
+               dbyte1 = dbyte0 + 1;
+               dbyte2 = dbyte0 + 2;
+
+               if (0 <= red_shift)
+                   *dbyte0 = (pixel & ximage_p->red_mask) >> red_shift;
+               else
+                   *dbyte0 = (pixel & ximage_p->red_mask) << -red_shift;
+
+               *dbyte1 = (pixel & ximage_p->green_mask) >> green_shift;
+
+               if (0 <= blue_shift)
+                   *dbyte2 = (pixel & ximage_p->blue_mask) >> blue_shift;
+               else
+                   *dbyte2 = (pixel & ximage_p->blue_mask) << -blue_shift;
+           }
+       } else {
+           bu_free(rows, "rows");
+           bu_free(idata, "image data");
+
+           bu_log("png: not supported for this platform\n");
+           return BRLCAD_ERROR;
+       }
+    }
+
+    bu_free(rows, "rows");
+    return BRLCAD_OK;
+}
+
+int
+X_openFb(struct dm *dmp)
+{
+    struct fb_platform_specific *fb_ps;
+    struct X24_fb_info *xfb_ps;
+    struct dm_xvars *pubvars = (struct dm_xvars *)dmp->i->dm_vars.pub_vars;
+    struct x_vars *privars = (struct x_vars *)dmp->i->dm_vars.priv_vars;
+
+    fb_ps = fb_get_platform_specific(FB_X24_MAGIC);
+    xfb_ps = (struct X24_fb_info *)fb_ps->data;
+    xfb_ps->dpy = pubvars->dpy;
+    xfb_ps->win = privars->pix;
+    xfb_ps->cwinp = pubvars->win;
+    xfb_ps->cmap = pubvars->cmap;
+    xfb_ps->vip = pubvars->vip;
+    xfb_ps->gc = privars->gc;
+
+    dmp->i->fbp = fb_open_existing("X", dm_get_width(dmp), dm_get_height(dmp), 
fb_ps);
+    fb_put_platform_specific(fb_ps);
+    return 0;
+}
+
+struct bu_structparse X_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}
+};
+
+/* Display Manager package interface */
+struct dm_impl dm_X_impl = {
+    X_close,
+    X_drawBegin,
+    X_drawEnd,
+    X_normal,
+    X_loadMatrix,
+    null_loadPMatrix,
+    X_drawString2D,
+    X_drawLine2D,
+    X_drawLine3D,
+    X_drawLines3D,
+    X_drawPoint2D,
+    null_drawPoint3D,
+    null_drawPoints3D,
+    X_drawVList,
+    X_drawVList,
+    X_draw,
+    X_setFGColor,
+    X_setBGColor,
+    X_setLineAttr,
+    X_configureWin,
+    X_setWinBounds,
+    X_setLight,
+    null_setTransparency,
+    null_setDepthMask,
+    X_setZBuffer,
+    X_debug,
+    X_logfile,
+    null_beginDList,
+    null_endDList,
+    null_drawDList,
+    null_freeDLists,
+    null_genDLists,
+    NULL,
+    X_getDisplayImage, /* display to image function */
+    X_reshape,
+    null_makeCurrent,
+    X_openFb,
+    NULL,
+    NULL,
+    0,
+    0,                         /* no displaylist */
+    0,                            /* no stereo */
+    PLOTBOUND,                 /* zoom-in limit */
+    1,                         /* bound flag */
+    "X",
+    "X Window System (X11)",
+    DM_TYPE_X,
+    1,
+    0,
+    0,
+    0, /* bytes per pixel */
+    0, /* bits per channel */
+    0,
+    0,
+    1.0, /* aspect ratio */
+    0,
+    {0, 0},
+    NULL,
+    NULL,
+    BU_VLS_INIT_ZERO,          /* bu_vls path name*/
+    BU_VLS_INIT_ZERO,          /* bu_vls full name drawing window */
+    BU_VLS_INIT_ZERO,          /* bu_vls short name drawing window */
+    {0, 0, 0},                 /* bg color */
+    {0, 0, 0},                 /* fg color */
+    {GED_MIN, GED_MIN, GED_MIN},       /* clipmin */
+    {GED_MAX, GED_MAX, GED_MAX},       /* clipmax */
+    0,                         /* no debugging */
+    BU_VLS_INIT_ZERO,          /* bu_vls logfile */
+    0,                         /* no perspective */
+    0,                         /* no lighting */
+    0,                         /* no transparency */
+    0,                         /* depth buffer is not writable */
+    0,                         /* no zbuffer */
+    0,                         /* no zclipping */
+    1,                          /* clear back buffer after drawing and swap */
+    0,                          /* not overriding the auto font size */
+    X_vparse,
+    FB_NULL,
+    0                          /* Tcl interpreter */
+};
+
+struct dm dm_X = { &dm_X_impl };
+
+/* Because class is actually used to access a struct
+ * entry in this file, preserve our redefinition
+ * of class for the benefit of avoiding C++ name
+ * collisions until the end of this file */
+#undef class
+
+#endif /* DM_X */
+
+/*
+ * Local Variables:
+ * mode: C
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * c-file-style: "stroustrup"
+ * End:
+ * ex: shiftwidth=4 tabstop=8
+ */

Copied: brlcad/branches/dm-fb-merge/src/libdm/X/dm-X.h (from rev 75426, 
brlcad/branches/dm-fb-merge/src/libdm/dm-X.h)
===================================================================
--- brlcad/branches/dm-fb-merge/src/libdm/X/dm-X.h                              
(rev 0)
+++ brlcad/branches/dm-fb-merge/src/libdm/X/dm-X.h      2020-04-16 21:11:44 UTC 
(rev 75427)
@@ -0,0 +1,60 @@
+/*                          D M - 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-X.h
+ *
+ */
+
+#ifndef DM_X_H
+#define DM_X_H
+
+#include "common.h"
+
+
+#define CMAP_BASE 40
+#define CUBE_DIMENSION 6
+#define NUM_PIXELS 216    /* CUBE_DIMENSION * CUBE_DIMENSION * CUBE_DIMENSION 
*/
+#define ColormapNull (Colormap *)NULL
+
+struct x_vars {
+    GC gc;
+    Pixmap pix;
+    fastf_t *xmat;
+    mat_t mod_mat;             /* default model transformation matrix */
+    mat_t disp_mat;            /* display transformation matrix */
+    int is_trueColor;
+    unsigned long bd, bg, fg;   /* color of border, background, foreground */
+    unsigned long pixels[NUM_PIXELS];
+    fastf_t ppmm_x;            /* pixel per mm in x */
+    fastf_t ppmm_y;            /* pixel per mm in y */
+};
+
+#endif /* DM_X_H */
+/** @} */
+/*
+ * Local Variables:
+ * mode: C
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * c-file-style: "stroustrup"
+ * End:
+ * ex: shiftwidth=4 tabstop=8
+ */

Copied: brlcad/branches/dm-fb-merge/src/libdm/X/fb_X.h (from rev 75426, 
brlcad/branches/dm-fb-merge/src/libdm/fb_X.h)
===================================================================
--- brlcad/branches/dm-fb-merge/src/libdm/X/fb_X.h                              
(rev 0)
+++ brlcad/branches/dm-fb-merge/src/libdm/X/fb_X.h      2020-04-16 21:11:44 UTC 
(rev 75427)
@@ -0,0 +1,56 @@
+/*                        F B _ X . H
+ * BRL-CAD
+ *
+ * Copyright (c) 2014-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 libfb */
+/** @{*/
+/** @file fb_X.h
+ *
+ * Structure holding information necessary for embedding a
+ * framebuffer in an X11 parent window.  This is NOT public API
+ * for libfb, and is not guaranteed to be stable from one
+ * release to the next.
+ *
+ */
+/** @} */
+
+#ifdef FB_USE_INTERNAL_API
+#ifdef IF_X
+#include "common.h"
+#include <X11/X.h>
+
+struct X24_fb_info {
+    Display *dpy;
+    Window win;
+    Window cwinp;
+    Colormap cmap;
+    XVisualInfo *vip;
+    GC gc;
+};
+#endif /* IF_X */
+#endif /* FB_USE_INTERNAL_API */
+
+/*
+ * Local Variables:
+ * mode: C
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * c-file-style: "stroustrup"
+ * End:
+ * ex: shiftwidth=4 tabstop=8
+ */

Copied: brlcad/branches/dm-fb-merge/src/libdm/X/if_X24.c (from rev 75426, 
brlcad/branches/dm-fb-merge/src/libdm/if_X24.c)
===================================================================
--- brlcad/branches/dm-fb-merge/src/libdm/X/if_X24.c                            
(rev 0)
+++ brlcad/branches/dm-fb-merge/src/libdm/X/if_X24.c    2020-04-16 21:11:44 UTC 
(rev 75427)
@@ -0,0 +1,3568 @@
+/*                        I F _ X 2 4 . C
+ * BRL-CAD
+ *
+ * Copyright (c) 1994 Sun Microsystems, Inc. - All Rights Reserved.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL SUN MICROSYSTEMS INC. BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
+ * OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF SUN
+ * MICROSYSTEMS INC. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * SUN MICROSYSTEMS INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER
+ * IS ON AN "AS IS" BASIS, AND SUN MICROSYSTEMS INC. HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+/** @addtogroup libstruct fb */
+/** @{*/
+/** @file if_X24.c
+ *
+ * X Window System (X11) libfb interface, supporting 24-, 8-, and
+ * 1-bit displays.
+ *
+ */
+/** @} */
+
+#include "common.h"
+
+#ifdef IF_X
+
+#include <errno.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/types.h>
+#include <string.h>
+#ifdef HAVE_SYS_TIME_H
+#  include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_MMAN_H
+#  include <sys/mman.h>
+#  define CAN_LINGER 1
+#  undef HAVE_SYS_SHM_H                /* Don't use both ways, mmap is 
preferred. */
+#else
+#  ifdef HAVE_SYS_SHM_H
+#    include <sys/ipc.h>
+#    include <sys/shm.h>
+#    define CAN_LINGER 1
+#  endif
+#endif
+
+#include <X11/X.h>
+#ifdef HAVE_XOSDEFS_H
+#  include <X11/Xfuncproto.h>
+#  include <X11/Xosdefs.h>
+#endif
+#if defined(linux)
+#  undef X_NOT_STDC_ENV
+#  undef X_NOT_POSIX
+#endif
+#define class REDEFINE_CLASS_STRING_TO_AVOID_CXX_CONFLICT
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+
+#include <ctype.h>
+
+#include "bu/color.h"
+#include "bu/file.h"
+#include "bu/malloc.h"
+#include "bu/str.h"
+#include "fb_private.h"
+#include "./fb_X.h"
+
+
+/*
+ * Per window state information.
+ */
+struct xinfo {
+    Display *xi_dpy;   /* Display and Screen(s) info */
+    Window xi_win;     /* Window ID */
+    int xi_screen;     /* Our screen selection */
+    Visual *xi_visual; /* Our visual selection */
+    XVisualInfo xi_visinfo;    /* Visual Info */
+    int xi_depth;      /* Depth of our window */
+    GC xi_gc;          /* current graphics context */
+    GC xi_cgc;         /* graphics context for clipping */
+    Region xi_reg;     /* Valid displayed region */
+    int xi_usereg;     /* Flag determining whether or not to use regions */
+    Colormap xi_cmap;  /* Colormap */
+    XImage *xi_image;  /* XImage (size of screen) */
+    Window xi_cwinp;   /* Cursor's Parent Window ID */
+    Window xi_cwin;    /* Cursor Window ID */
+    unsigned long xi_wp;       /* White pixel */
+    unsigned long xi_bp;       /* Black pixel */
+
+    /*
+     * Pixel buffer usage:
+     *
+     * xi_mem is the actual data received from the user.  It's stored
+     * in 24-bit RGB format, in image-space coordinates.
+     *
+     * xi_pix is the panned, zoomed, and possibly colormapped output
+     * image.  It's stored in whatever X11 format makes sense for our
+     * Visual, in X11-space coordinates.  This is the buffer backing
+     * xi_image.
+     *
+     */
+
+    unsigned char *xi_mem;     /* 24-bit backing store */
+    unsigned char *xi_pix;     /* X Image buffer */
+
+#ifdef HAVE_SYS_SHM_H
+    int xi_shmid;              /* Sys V shared mem id */
+#endif
+
+    unsigned long xi_mode;     /* 0, 1, 2 */
+    unsigned long xi_flags;
+
+    ColorMap *xi_rgb_cmap;     /* User's libfb colormap */
+    unsigned char *xi_redmap;  /* Fake colormap for non-DirectColor */
+    unsigned char *xi_blumap;  /* Fake colormap for non-DirectColor */
+    unsigned char *xi_grnmap;  /* Fake colormap for non-DirectColor */
+
+    unsigned char *xi_ccredtbl;        /* Lookup table for red component */
+    unsigned char *xi_ccgrntbl;        /* Lookup table for green component */
+    unsigned char *xi_ccblutbl;        /* Lookup table for blue component */
+
+    unsigned char *xi_andtbl;  /* Lookup table for 1-bit dithering */
+    unsigned char *xi_ortbl;   /* Lookup table for 1-bit dithering */
+
+    size_t xi_ncolors;         /* Number of colors in colorcube */
+    unsigned int xi_base;      /* Base color in colorcube */
+
+    /* The following values are in Image Pixels */
+
+    int xi_iwidth;     /* Width of user's whole image */
+    int xi_iheight;    /* Height of user's whole image */
+
+    int xi_ilf;                /* Image coordinate of LLHC image */
+    int xi_ibt;                /* pixel */
+    int xi_irt;                /* Image coordinate of URHC image */
+    int xi_itp;                /* pixel */
+
+    /* The following values are in X Pixels */
+
+    int xi_ilf_w;      /* Width of leftmost image pixels */
+    int xi_irt_w;      /* Width of rightmost image pixels */
+    int xi_ibt_h;      /* Height of bottommost image pixels */
+    int xi_itp_h;      /* Height of topmost image pixels */
+
+    int xi_xwidth;     /* Width of X window */
+    int xi_xheight;    /* Height of X window */
+
+    int xi_xlf;                /* X-coord of leftmost pixels */
+    int xi_xrt;                /* X-coord of rightmost pixels */
+    int xi_xtp;                /* Y-coord of topmost pixels */
+    int xi_xbt;                /* Y-coord of bottommost pixels */
+};
+#define XI(ptr) ((struct xinfo *)((ptr)->i->u1.p))
+#define XI_SET(ptr, val) ((ptr)->i->u1.p) = (char *) val;
+
+
+/* Flags in xi_flags */
+
+#define FLG_VMASK       0x07   /* Visual mask */
+                               /* Note: values below are in preference order*/
+#define FLG_VD24        0x01   /* 24-bit DirectColor */
+#define FLG_VT24        0x02   /* 24-bit TrueColor */
+#define FLG_VD16        0x03   /* 16-bit DirectColor */
+#define FLG_VT16        0x04   /* 16-bit TrueColor */
+#define FLG_VP8         0x05   /* 8-bit PseudoColor */
+#define FLG_VS8         0x06   /* 8-bit StaticGray */
+#define FLG_VG8         0x07   /* 8-bit GrayScale */
+#define FLG_VS1         0x08   /* 1-bit StaticGray */
+
+#define FLG_LINCMAP 0x10       /* We're using a linear colormap */
+#define FLG_XCMAP   0x20       /* The X server can do colormapping for us */
+#define FLG_INIT    0x40       /* Display is fully initialized */
+
+/* Mode flags for open */
+
+#define MODE1_MASK     (1<<1)
+#define MODE1_TRANSIENT        (0<<1)
+#define MODE1_LINGERING (1<<1)
+
+#define MODEV_MASK     (7<<1)
+
+#define MODE10_MASK    (1<<10)
+#define MODE10_MALLOC  (0<<10)
+#define MODE10_SHARED  (1<<10)
+
+#define MODE11_MASK    (1<<11)
+#define MODE11_NORMAL  (0<<11)
+#define MODE11_ZAP     (1<<11)
+
+static struct modeflags {
+    char c;
+    unsigned long mask;
+    unsigned long value;
+    char *help;
+} modeflags[] = {
+    { 'l',     MODE1_MASK, MODE1_LINGERING,
+      "Lingering window" },
+    { 't',     MODE1_MASK, MODE1_TRANSIENT,
+      "Transient window" },
+    { 's',  MODE10_MASK, MODE10_SHARED,
+      "Use shared memory backing store" },
+    { 'z',     MODE11_MASK, MODE11_ZAP,
+      "Zap (free) shared memory and exit" },
+    { 'D',     MODEV_MASK, FLG_VD24 << 1,
+      "Select 24-bit DirectColor display if available" },
+    { 'T',     MODEV_MASK, FLG_VT24 << 1,
+      "Select 24-bit TrueColor display if available" },
+    { 'P',     MODEV_MASK, FLG_VP8 << 1,
+      "Select 8-bit PseudoColor display if available" },
+    { 'S',     MODEV_MASK, FLG_VS8 << 1,
+      "Select 8-bit StaticGray display if available" },
+    { 'G',     MODEV_MASK, FLG_VG8 << 1,
+      "Select 8-bit GrayScale display if available" },
+    { 'M',     MODEV_MASK, FLG_VS1 << 1,
+      "Select 1-bit StaticGray display if available" },
+    { '\0', 0, 0, "" }
+};
+
+
+/* Flags for X24_blit's flags argument */
+
+#define BLIT_DISP 0x1  /* Write bits to screen */
+#define BLIT_PZ 0x2    /* This is a pan or zoom */
+#define BLIT_RESIZE 0x4        /* We just resized (screen empty) */
+
+#define BS_NAME "/tmp/X24_fb"
+
+/* Elements of 6x9x4 colorcube */
+
+static unsigned char reds[] = { 0, 51, 102, 153, 204, 255 };
+static unsigned char grns[] = { 0, 32, 64, 96, 128, 159, 191, 223, 255 };
+static unsigned char blus[] = { 0, 85, 170, 255 };
+
+/* Dither masks */
+
+static float dmsk881[] = {
+    0.705882, 0.956863, 0.235294, 0.486275, 0.737255, 0.988235, 0.203922, 
0.454902,
+    0.172549, 0.423529, 0.674510, 0.925490, 0.141176, 0.392157, 0.643137, 
0.894118,
+    0.580392, 0.831373, 0.109804, 0.360784, 0.611765, 0.862745, 0.078431, 
0.329412,
+    0.047059, 0.298039, 0.549020, 0.800000, 0.015686, 0.266667, 0.517647, 
0.768628,
+    0.721569, 0.972549, 0.188235, 0.439216, 0.690196, 0.941177, 0.219608, 
0.470588,
+    0.125490, 0.376471, 0.627451, 0.878431, 0.156863, 0.407843, 0.658824, 
0.909804,
+    0.596078, 0.847059, 0.062745, 0.313726, 0.564706, 0.815686, 0.094118, 
0.345098,
+    0.000000, 0.250980, 0.501961, 0.752941, 0.031373, 0.282353, 0.533333, 
0.784314
+};
+
+
+static float dmsk883[] = {
+    0.784314, 0.533333, 0.282353, 0.031373, 0.752941, 0.501961, 0.250980, 
0.000000,
+    0.345098, 0.094118, 0.815686, 0.564706, 0.313726, 0.062745, 0.847059, 
0.596078,
+    0.909804, 0.658824, 0.407843, 0.156863, 0.878431, 0.627451, 0.376471, 
0.125490,
+    0.470588, 0.219608, 0.941177, 0.690196, 0.439216, 0.188235, 0.972549, 
0.721569,
+    0.768628, 0.517647, 0.266667, 0.015686, 0.800000, 0.549020, 0.298039, 
0.047059,
+    0.329412, 0.078431, 0.862745, 0.611765, 0.360784, 0.109804, 0.831373, 
0.580392,
+    0.894118, 0.643137, 0.392157, 0.141176, 0.925490, 0.674510, 0.423529, 
0.172549,
+    0.454902, 0.203922, 0.988235, 0.737255, 0.486275, 0.235294, 0.956863, 
0.705882,
+
+    0.988235, 0.737255, 0.486275, 0.235294, 0.956863, 0.705882, 0.454902, 
0.203922,
+    0.392157, 0.141176, 0.925490, 0.674510, 0.423529, 0.172549, 0.894118, 
0.643137,
+    0.862745, 0.611765, 0.360784, 0.109804, 0.831373, 0.580392, 0.329412, 
0.078431,
+    0.266667, 0.015686, 0.800000, 0.549020, 0.298039, 0.047059, 0.768628, 
0.517647,
+    0.941177, 0.690196, 0.439216, 0.188235, 0.972549, 0.721569, 0.470588, 
0.219608,
+    0.407843, 0.156863, 0.878431, 0.627451, 0.376471, 0.125490, 0.909804, 
0.658824,
+    0.815686, 0.564706, 0.313726, 0.062745, 0.847059, 0.596078, 0.345098, 
0.094118,
+    0.282353, 0.031373, 0.752941, 0.501961, 0.250980, 0.000000, 0.784314, 
0.533333,
+
+    0.000000, 0.250980, 0.501961, 0.752941, 0.031373, 0.282353, 0.533333, 
0.784314,
+    0.596078, 0.847059, 0.062745, 0.313726, 0.564706, 0.815686, 0.094118, 
0.345098,
+    0.125490, 0.376471, 0.627451, 0.878431, 0.156863, 0.407843, 0.658824, 
0.909804,
+    0.721569, 0.972549, 0.188235, 0.439216, 0.690196, 0.941177, 0.219608, 
0.470588,
+    0.047059, 0.298039, 0.549020, 0.800000, 0.015686, 0.266667, 0.517647, 
0.768628,
+    0.580392, 0.831373, 0.109804, 0.360784, 0.611765, 0.862745, 0.078431, 
0.329412,
+    0.172549, 0.423529, 0.674510, 0.925490, 0.141176, 0.392157, 0.643137, 
0.894118,
+    0.705882, 0.956863, 0.235294, 0.486275, 0.737255, 0.988235, 0.203922, 
0.454902
+};
+
+
+/* Luminance factor tables (filled in in x24_setup()) */
+
+static int lumdone = 0;                /* Nonzero if tables valid */
+static unsigned long rlumtbl[256];
+static unsigned long glumtbl[256];
+static unsigned long blumtbl[256];
+
+/*
+ * A given Display (i.e. Server) can have any number of Screens.  Each
+ * Screen can support one or more Visual types.
+ *
+ * unix:0.1.2 => host:display.screen.visual
+ *
+ * Typically the screen and visual default to 0 by being omitted.
+ */
+HIDDEN void
+print_display_info(Display *dpy)
+{
+    int i;
+    int screen;
+    Visual *visual;
+    XVisualInfo *vp;
+    int num;
+    Window win = DefaultRootWindow(dpy);
+    XStandardColormap cmap;
+
+    printf("Server \"%s\", release %d\n",
+          ServerVendor(dpy), VendorRelease(dpy));
+
+    /* How many screens? */
+    screen = DefaultScreen(dpy);
+    printf("%d Screen(s), we connected to screen %d\n",
+          ScreenCount(dpy), screen);
+
+    /* How many visuals? */
+    vp = XGetVisualInfo(dpy, VisualNoMask, NULL, &num);
+    printf("%d Visual(s)\n", num);
+
+    printf("ImageByteOrder: %s\n",
+          ImageByteOrder(dpy) == MSBFirst ? "MSBFirst" : "LSBFirst");
+    printf("BitmapBitOrder: %s\n",
+          BitmapBitOrder(dpy) == MSBFirst ? "MSBFirst" : "LSBFirst");
+    printf("BitmapUnit: %d\n", BitmapUnit(dpy));
+    printf("BitmapPad: %d\n", BitmapPad(dpy));
+
+    printf("==== Screen %d ====\n", screen);
+    printf("%d x %d pixels, %d x %d mm, (%.2f x %.2f dpi)\n",
+          DisplayWidth(dpy, screen), DisplayHeight(dpy, screen),
+          DisplayWidthMM(dpy, screen), DisplayHeightMM(dpy, screen),
+          DisplayWidth(dpy, screen)*25.4/DisplayWidthMM(dpy, screen),
+          DisplayHeight(dpy, screen)*25.4/DisplayHeightMM(dpy, screen));
+    printf("%d DisplayPlanes (other Visuals, if any, may vary)\n",
+          DisplayPlanes(dpy, screen));
+    printf("%d DisplayCells\n", DisplayCells(dpy, screen));
+    printf("BlackPixel = %lu\n", BlackPixel(dpy, screen));
+    printf("WhitePixel = %lu\n", WhitePixel(dpy, screen));
+    printf("Save Unders: %s\n",
+          DoesSaveUnders(ScreenOfDisplay(dpy, screen)) ? "True" : "False");
+    i = DoesBackingStore(ScreenOfDisplay(dpy, screen));
+    printf("Backing Store: %s\n", i == WhenMapped ? "WhenMapped" :
+          (i == Always ? "Always" : "NotUseful"));
+    printf("Installed Colormaps: min %d, max %d\n",
+          MinCmapsOfScreen(ScreenOfDisplay(dpy, screen)),
+          MaxCmapsOfScreen(ScreenOfDisplay(dpy, screen)));
+    printf("DefaultColormap: 0x%lx\n", DefaultColormap(dpy, screen));
+
+
+    for (i = 0; i < num; i++) {
+
+       visual = vp[i].visual;
+
+       printf("---- Visual 0x%lx (%d)----\n", (unsigned long int)visual, i);
+
+       printf("screen: %d\n", vp[i].screen);
+       printf("depth : %d\n", vp[i].depth);
+
+       switch (visual->class) {
+           case DirectColor:
+               printf("DirectColor: Alterable RGB maps, pixel RGB subfield 
indices\n");
+               printf("RGB Masks: 0x%lx 0x%lx 0x%lx\n", visual->red_mask,
+                      visual->green_mask, visual->blue_mask);
+               break;
+           case TrueColor:
+               printf("TrueColor: Fixed RGB maps, pixel RGB subfield 
indices\n");
+               printf("RGB Masks: 0x%lx 0x%lx 0x%lx\n", visual->red_mask,
+                      visual->green_mask, visual->blue_mask);
+               break;
+           case PseudoColor:
+               printf("PseudoColor: Alterable RGB maps, single index\n");
+               break;
+           case StaticColor:
+               printf("StaticColor: Fixed RGB maps, single index\n");
+               break;
+           case GrayScale:
+               printf("GrayScale: Alterable map (R=G=B), single index\n");
+               break;
+           case StaticGray:
+               printf("StaticGray: Fixed map (R=G=B), single index\n");
+               break;
+           default:
+               printf("Unknown visual class %d\n",
+                      visual->class);
+               break;
+       }
+       printf("Map Entries: %d\n", visual->map_entries);
+       printf("Bits per RGB: %d\n", visual->bits_per_rgb);
+    }
+    XFree((char *) vp);
+
+
+    printf("==== Standard Colormaps ====\n");
+    if (XGetStandardColormap(dpy, win, &cmap, XA_RGB_BEST_MAP)) {
+       printf("XA_RGB_BEST_MAP    - Yes (0x%lx)\n", cmap.colormap);
+       printf("R[0..%lu] * %lu + G[0..%lu] * %lu  + B[0..%lu] * %lu + %lu\n",
+              cmap.red_max, cmap.red_mult, cmap.green_max, cmap.green_mult,
+              cmap.blue_max, cmap.blue_mult, cmap.base_pixel);
+    } else {
+       printf("XA_RGB_BEST_MAP    - No\n");
+    }
+    if (XGetStandardColormap(dpy, win, &cmap, XA_RGB_DEFAULT_MAP)) {
+       printf("XA_RGB_DEFAULT_MAP - Yes (0x%lx)\n", cmap.colormap);
+       printf("R[0..%lu] * %lu + G[0..%lu] * %lu  + B[0..%lu] * %lu + %lu\n",
+              cmap.red_max, cmap.red_mult, cmap.green_max, cmap.green_mult,
+              cmap.blue_max, cmap.blue_mult, cmap.base_pixel);
+    } else {
+       printf("XA_RGB_DEFAULT_MAP - No\n");
+    }
+    if (XGetStandardColormap(dpy, win, &cmap, XA_RGB_GRAY_MAP)) {
+       printf("XA_RGB_GRAY_MAP    - Yes (0x%lx)\n", cmap.colormap);
+       printf("R[0..%lu] * %lu + %lu\n",
+              cmap.red_max, cmap.red_mult, cmap.base_pixel);
+    } else {
+       printf("XA_RGB_GRAY_MAP    - No\n");
+    }
+}
+
+
+/*
+  Create 6x9x4 color cube.
+*/
+HIDDEN void
+X24_createColorCube(struct xinfo *xi)
+{
+    size_t i;
+    int redmul, grnmul;
+    unsigned long pixels[256], pmask[1], pixel[1];
+    XColor colors[256];
+
+    /*
+     * Color cube is in RGB order
+     */
+    grnmul = sizeof (blus);
+    redmul = sizeof (blus) * sizeof (grns);
+
+    XAllocColorCells(xi->xi_dpy, xi->xi_cmap, 1, pmask, 0, pixels,
+                    xi->xi_base + xi->xi_ncolors);
+
+    for (pixel[0] = 0; pixel[0] < xi->xi_base; pixel[0]++) {
+       XFreeColors(xi->xi_dpy, xi->xi_cmap, pixel, 1, 0);
+    }
+
+    /* Fill the colormap and the colorcube */
+    for (i = 0; i < xi->xi_ncolors; i++) {
+       colors[i].red = reds[i / redmul] << 8;
+       colors[i].green = grns[(i % redmul) / grnmul] << 8;
+       colors[i].blue = blus[i % grnmul] << 8;
+       colors[i].flags = DoRed | DoGreen | DoBlue;
+       colors[i].pixel = xi->xi_base + i;
+    }
+
+    XStoreColors(xi->xi_dpy, xi->xi_cmap, colors, xi->xi_ncolors);
+}
+
+
+/*
+  Create fast lookup tables for dithering
+*/
+HIDDEN void
+X24_createColorTables(struct xinfo *xi)
+{
+    int i, j;
+    size_t idx;
+    int redmul, grnmul;
+
+    grnmul = sizeof (blus);
+    redmul = sizeof (blus) * sizeof (grns);
+
+    xi->xi_ccredtbl = (unsigned char *)malloc(64 * 256);
+    xi->xi_ccgrntbl = (unsigned char *)malloc(64 * 256);
+    xi->xi_ccblutbl = (unsigned char *)malloc(64 * 256);
+
+    for (i = 0; i < 256; i++) {
+       int redval, grnval, bluval;
+       int redtbl, grntbl, blutbl;
+       int reditbl, grnitbl, bluitbl;
+
+       idx = i / (256 / (sizeof (reds) - 1));
+       reditbl = redtbl = idx * redmul;
+       if (idx < (sizeof (reds) - 1))
+           reditbl += redmul;
+       redval = reds[idx];
+
+       idx = i / (256 / (sizeof (grns) - 1));
+       grnitbl = grntbl = idx * grnmul;
+       if (idx < (sizeof (grns) - 1))
+           grnitbl += grnmul;
+       grnval = grns[idx];
+
+       idx = i / (256 / (sizeof (blus) - 1));
+       bluitbl = blutbl = idx;
+       if (idx < (sizeof (blus) - 1))
+           bluitbl++;
+       bluval = blus[idx];
+
+       for (j = 0; j < 64; j++) {
+           if (i - redval > (256 / (sizeof (reds) - 1)) * dmsk883[128+j]) {
+               xi->xi_ccredtbl[(i << 6) + j] = reditbl;
+           } else {
+               xi->xi_ccredtbl[(i << 6) + j] = redtbl;
+           }
+
+           if (i - grnval > (256 / (sizeof (grns) - 1)) * dmsk883[64+j]) {
+               xi->xi_ccgrntbl[(i << 6) + j] = grnitbl;
+           } else {
+               xi->xi_ccgrntbl[(i << 6) + j] = grntbl;
+           }
+
+           if (i - bluval > (256 / (sizeof (blus) - 1)) * dmsk883[j]) {
+               xi->xi_ccblutbl[(i << 6) + j] = bluitbl;
+           } else {
+               xi->xi_ccblutbl[(i << 6) + j] = blutbl;
+           }
+       }
+    }
+}
+
+
+HIDDEN int
+x24_setup(struct fb *ifp, int width, int height)
+{
+    struct xinfo *xi = XI(ifp);
+
+    XGCValues gcv;
+    XSizeHints xsh;            /* part of the "standard" props */
+    XWMHints xwmh;             /* size guidelines for window mngr */
+    XSetWindowAttributes xswa;
+    XRectangle rect;
+    char *xname;
+
+    FB_CK_FB(ifp->i);
+
+    /* Save these in state structure */
+
+    xi->xi_xwidth = width;
+    xi->xi_xheight = height;
+
+    /* Open the display - use the env variable DISPLAY */
+    xname = XDisplayName(NULL);
+    /* Attempt one level of fallback, esp. for fbserv daemon */
+    if (!xname || *xname == '\0') xname = ":0";
+
+    if ((xi->xi_dpy = XOpenDisplay(xname)) == NULL) {
+       fb_log("if_X: Can't open X display \"%s\"\n", xname);
+       return -1;
+    }
+
+    /* Use the screen we connected to */
+    xi->xi_screen = DefaultScreen(xi->xi_dpy);
+
+    /*
+     * Here we try to get the best possible visual that's no better than the
+     * one that the user asked for.  Note that each case falls through to
+     * the next.
+     */
+
+    switch ((xi->xi_mode & MODEV_MASK) >> 1) {
+       default:
+       case FLG_VD24:
+           if (XMatchVisualInfo(xi->xi_dpy, xi->xi_screen, 24, DirectColor,
+                                &xi->xi_visinfo)) {
+               xi->xi_flags |= FLG_XCMAP | FLG_VD24;
+               break;
+           }
+           /*FALLTHROUGH*/
+       case FLG_VT24:
+           if (XMatchVisualInfo(xi->xi_dpy, xi->xi_screen, 24, TrueColor,
+                                &xi->xi_visinfo)) {
+               xi->xi_flags |= FLG_VT24;
+               break;
+           }
+           /*FALLTHROUGH*/
+       case FLG_VD16:
+           if (XMatchVisualInfo(xi->xi_dpy, xi->xi_screen, 16, DirectColor,
+                                &xi->xi_visinfo)) {
+               xi->xi_flags |= FLG_XCMAP | FLG_VD16;
+               break;
+           }
+           /*FALLTHROUGH*/
+       case FLG_VT16:
+           if (XMatchVisualInfo(xi->xi_dpy, xi->xi_screen, 16, TrueColor,
+                                &xi->xi_visinfo)) {
+               xi->xi_flags |= FLG_VT16;
+               break;
+           }
+           /*FALLTHROUGH*/
+       case FLG_VP8:
+           if (XMatchVisualInfo(xi->xi_dpy, xi->xi_screen, 8, PseudoColor,
+                                &xi->xi_visinfo)) {
+               xi->xi_flags |= FLG_VP8;
+               break;
+           }
+           /*FALLTHROUGH*/
+       case FLG_VS8:
+           if (XMatchVisualInfo(xi->xi_dpy, xi->xi_screen, 8, StaticGray,
+                                &xi->xi_visinfo)) {
+               xi->xi_flags |= FLG_VS8;
+               break;
+           }
+           /*FALLTHROUGH*/
+       case FLG_VG8:
+           if (XMatchVisualInfo(xi->xi_dpy, xi->xi_screen, 8, GrayScale,
+                                &xi->xi_visinfo)) {
+               xi->xi_flags |= FLG_VG8;
+               break;
+           }
+           /*FALLTHROUGH*/
+       case FLG_VS1:
+           if (XMatchVisualInfo(xi->xi_dpy, xi->xi_screen, 1, StaticGray,
+                                &xi->xi_visinfo)) {
+               xi->xi_flags |= FLG_VS1;
+               break;
+           }
+           /*FALLTHROUGH*/
+           fb_log("if_X24: Can't get supported Visual on X display \"%s\"\n",
+                  XDisplayName(NULL));
+           print_display_info(xi->xi_dpy);
+           return -1;
+    }
+
+    xi->xi_visual = xi->xi_visinfo.visual;
+    xi->xi_depth = xi->xi_visinfo.depth;
+
+    /* Set up colormaps, white/black pixels */
+
+    switch (xi->xi_flags & FLG_VMASK) {
+       case FLG_VD24:
+           xi->xi_cmap = XCreateColormap(xi->xi_dpy, RootWindow(xi->xi_dpy,
+                                                                
xi->xi_screen), xi->xi_visual, AllocAll);
+           xi->xi_wp = 0xFFFFFF;
+           xi->xi_bp = 0x000000;
+           break;
+
+       case FLG_VT24:
+           /*
+            * We need this colormap, even though we're not really going to
+            * use it, because if we don't specify a colormap when we
+            * create the window (thus getting the default), and the
+            * default visual is not 24-bit, the window create will fail.
+            */
+
+           xi->xi_cmap = XCreateColormap(xi->xi_dpy, RootWindow(xi->xi_dpy,
+                                                                
xi->xi_screen), xi->xi_visual, AllocNone);
+           xi->xi_wp = 0xFFFFFF;
+           xi->xi_bp = 0x000000;
+           break;
+
+       case FLG_VD16:
+           xi->xi_cmap = XCreateColormap(xi->xi_dpy, RootWindow(xi->xi_dpy,
+                                                                
xi->xi_screen), xi->xi_visual, AllocAll);
+           xi->xi_wp = 0xFFFFFF;
+           xi->xi_bp = 0x000000;
+           break;
+
+       case FLG_VT16:
+           /*
+            * We need this colormap, even though we're not really going to
+            * use it, because if we don't specify a colormap when we
+            * create the window (thus getting the default), and the
+            * default visual is not 24-bit, the window create will fail.
+            */
+
+           xi->xi_cmap = XCreateColormap(xi->xi_dpy, RootWindow(xi->xi_dpy,
+                                                                
xi->xi_screen), xi->xi_visual, AllocNone);
+           xi->xi_wp = 0xFFFFFF;
+           xi->xi_bp = 0x000000;
+           break;
+
+       case FLG_VP8:
+           {
+               xi->xi_cmap = XCreateColormap(xi->xi_dpy, RootWindow(xi->xi_dpy,
+                                                                    
xi->xi_screen), xi->xi_visual, AllocNone);
+
+               xi->xi_ncolors = sizeof (reds) * sizeof (blus) * sizeof (grns);
+               xi->xi_base = 255 - xi->xi_ncolors;
+
+               /* Create color cube */
+               X24_createColorCube(xi);
+
+               /* Create fast lookup tables for dithering */
+               X24_createColorTables(xi);
+
+               /* Do white/black pixels */
+               xi->xi_bp = xi->xi_base;
+               xi->xi_wp = xi->xi_base + xi->xi_ncolors - 1;
+
+               break;
+           }
+
+       case FLG_VS8:
+           /*
+            * We need this colormap, even though we're not really going to
+            * use it, because if we don't specify a colormap when we
+            * create the window (thus getting the default), and the
+            * default visual is not 8-bit, the window create will fail.
+            */
+
+           xi->xi_cmap = XCreateColormap(xi->xi_dpy, RootWindow(xi->xi_dpy,
+                                                                
xi->xi_screen), xi->xi_visual, AllocNone);
+           xi->xi_wp = 0xFF;
+           xi->xi_bp = 0x00;
+           break;
+
+       case FLG_VG8:
+           {
+               /*
+                * We're being a little lazy here by just taking over the
+                * entire colormap and writing a linear ramp to it.  If we
+                * didn't take the whole thing we might be able to avoid a
+                * little colormap flashing, but then we'd need separate
+                * display code for GrayScale and StaticGray and I'm just not
+                * sure it's worth it.
+                */
+
+               int i;
+               XColor colors[256];
+
+               xi->xi_cmap = XCreateColormap(xi->xi_dpy, RootWindow(xi->xi_dpy,
+                                                                    
xi->xi_screen), xi->xi_visual, AllocAll);
+
+               /* Fill the colormap and the colorcube */
+
+               for (i = 0; i < 255; i++) {
+                   colors[i].red = i << 8;
+                   colors[i].green = i << 8;
+                   colors[i].blue = i << 8;
+                   colors[i].flags = DoRed | DoGreen | DoBlue;
+                   colors[i].pixel = i;
+               }
+
+               XStoreColors(xi->xi_dpy, xi->xi_cmap, colors, 256);
+
+               /* Do white/black pixels */
+
+               xi->xi_bp = 0x00;
+               xi->xi_wp = 0xFF;
+               break;
+           }
+       case FLG_VS1:
+           {
+               int i, j, x, didx;
+
+               /*
+                * We need this colormap, even though we're not really going to
+                * use it, because if we don't specify a colormap when we
+                * create the window (thus getting the default), and the
+                * default visual is not 1-bit, the window create will fail.
+                */
+
+               xi->xi_cmap = XCreateColormap(xi->xi_dpy, RootWindow(xi->xi_dpy,
+                                                                    
xi->xi_screen), xi->xi_visual, AllocNone);
+
+               /* Create fast lookup tables for dithering */
+
+               xi->xi_andtbl = (unsigned char *)malloc(64 * 256);
+               xi->xi_ortbl = (unsigned char *)malloc(64 * 256);
+
+               for (i = 0; i < 256; i++)
+                   for (j = 0; j < 64; j++) {
+                       didx = j;
+                       x = 7 - (j & 0x7);
+
+                       if (i > (256.0 * dmsk881[didx])) {
+                           xi->xi_andtbl[(i << 6) + j] = 0xFF;
+                           xi->xi_ortbl[(i << 6) + j] = 1 << x;
+                       } else {
+                           xi->xi_andtbl[(i << 6) + j] = ~(1 << x);
+                           xi->xi_ortbl[(i << 6) + j] = 0;
+                       }
+                   }
+
+               xi->xi_wp = 0x0;
+               xi->xi_bp = 0x1;
+               break;
+           }
+    }
+
+    /* Create fake colormaps if the X server won't do it for us */
+
+    if (!(xi->xi_flags & FLG_XCMAP)) {
+       xi->xi_redmap = (unsigned char *)malloc(256);
+       xi->xi_grnmap = (unsigned char *)malloc(256);
+       xi->xi_blumap = (unsigned char *)malloc(256);
+
+       if (!xi->xi_redmap || !xi->xi_grnmap || !xi->xi_blumap) {
+           fb_log("if_X24: Can't allocate colormap memory\n");
+           return -1;
+       }
+    }
+
+    /*
+     * Fill in XSetWindowAttributes struct for XCreateWindow.
+     */
+    xswa.event_mask = ExposureMask | ButtonPressMask | StructureNotifyMask;
+    xswa.background_pixel = xi->xi_bp;
+    xswa.border_pixel = xi->xi_wp;
+    xswa.bit_gravity = ForgetGravity;
+    xswa.backing_store = Always;
+    xswa.colormap = xi->xi_cmap;
+
+    xi->xi_win = XCreateWindow(xi->xi_dpy, RootWindow(xi->xi_dpy,
+                                                     xi->xi_screen), 0, 0, 
width, height, 3, xi->xi_depth,
+                              InputOutput, xi->xi_visual, CWEventMask | 
CWBackPixel |
+                              CWBorderPixel | CWBitGravity | CWBackingStore | 
CWColormap,
+                              &xswa);
+    xi->xi_cwinp = xi->xi_win;
+
+    if (xi->xi_win == 0) {
+       fb_log("if_X: Can't create window\n");
+       return -1;
+    }
+
+    /* Tell window manager about colormap */
+
+    XSetWindowColormap(xi->xi_dpy, xi->xi_win, xi->xi_cmap);
+
+    /*
+     * Fill in XSizeHints struct to inform window
+     * manager about initial size and location.
+     */
+    xsh.flags = PPosition | PSize | PMinSize | PMaxSize;
+    xsh.width = width;
+    xsh.max_width = ifp->i->if_max_width;
+    xsh.min_width = 0;
+    xsh.height = height;
+    xsh.max_height = ifp->i->if_max_height;
+    xsh.min_height = 0;
+    xsh.x = xsh.y = 0;
+
+    /* Set standard properties for Window Managers */
+
+    XSetStandardProperties(xi->xi_dpy, xi->xi_win,
+                          "Frame buffer",              /* window name */
+                          "Frame buffer",              /* icon name */
+                          None,                        /* icon pixmap */
+                          NULL, 0,             /* command (argv, argc) */
+                          &xsh);                       /* size hints */
+
+    xwmh.input = False;                /* no terminal input? */
+    xwmh.initial_state = NormalState;
+    xwmh.flags = InputHint | StateHint;
+    XSetWMHints(xi->xi_dpy, xi->xi_win, &xwmh);
+
+    /* Create a Graphics Context for drawing */
+
+    gcv.foreground = xi->xi_wp;
+    gcv.background = xi->xi_bp;
+    xi->xi_gc = XCreateGC(xi->xi_dpy, xi->xi_win,
+                         GCForeground | GCBackground, &gcv);
+
+    /* Create a Graphics Context for clipping */
+
+    gcv.foreground = xi->xi_bp;
+    gcv.background = xi->xi_bp;
+    xi->xi_cgc = XCreateGC(xi->xi_dpy, xi->xi_win,
+                          GCForeground | GCBackground, &gcv);
+
+    /* Initialize the valid region */
+    xi->xi_usereg = 1;
+    xi->xi_reg = XCreateRegion();
+    rect.x = 0;
+    rect.y = 0;
+    rect.width = xi->xi_xwidth;
+    rect.height = xi->xi_xheight;
+    XUnionRectWithRegion(&rect, xi->xi_reg, xi->xi_reg);
+
+    /* Map window to screen */
+
+    XMapWindow(xi->xi_dpy, xi->xi_win);
+    XFlush(xi->xi_dpy);
+
+    /* Allocate image buffer, and make our X11 Image */
+
+    switch (xi->xi_flags & FLG_VMASK) {
+       case FLG_VD24:
+       case FLG_VT24:
+           if ((xi->xi_pix = (unsigned char *) calloc(sizeof(unsigned int),
+                                                      width*height)) == NULL) {
+               fb_log("X24_open: pix32 malloc failed\n");
+               return -1;
+           }
+
+           xi->xi_image = XCreateImage(xi->xi_dpy,
+                                       xi->xi_visual, xi->xi_depth, ZPixmap, 0,
+                                       (char *) xi->xi_pix, width, height,
+                                       sizeof(unsigned int) * 8, 0);
+           break;
+
+       case FLG_VD16:
+       case FLG_VT16:
+           if ((xi->xi_pix = (unsigned char *) calloc(2, width*height)) == 
NULL) {
+               fb_log("X24_open: pix32 malloc failed\n");
+               return -1;
+           }
+
+           xi->xi_image = XCreateImage(xi->xi_dpy,
+                                       xi->xi_visual, xi->xi_depth, ZPixmap, 0,
+                                       (char *) xi->xi_pix, width, height,
+                                       16, 0);
+           break;
+
+       case FLG_VP8:
+       case FLG_VS8:
+       case FLG_VG8:
+           if ((xi->xi_pix = (unsigned char *) calloc(sizeof(char),
+                                                      width*height)) == NULL) {
+               fb_log("X24_open: pix8 malloc failed\n");
+               return -1;
+           }
+           memset(xi->xi_pix, xi->xi_bp, width*height);
+
+           xi->xi_image = XCreateImage(xi->xi_dpy,
+                                       xi->xi_visual, xi->xi_depth, ZPixmap, 0,
+                                       (char *) xi->xi_pix, width, height, 8, 
0);
+           break;
+
+       case FLG_VS1:
+           xi->xi_image = XCreateImage(xi->xi_dpy,
+                                       xi->xi_visual, xi->xi_depth, XYBitmap, 
0,
+                                       NULL, width, height, 32, 0);
+
+           if ((xi->xi_pix = (unsigned char *) calloc(sizeof(char),
+                                                      
xi->xi_image->bytes_per_line * height)) == NULL) {
+               fb_log("X24_open: pix_1 malloc failed\n");
+               return -1;
+           }
+           xi->xi_image->data = (char *) xi->xi_pix;
+           xi->xi_image->byte_order = MSBFirst;
+           xi->xi_image->bitmap_bit_order = MSBFirst;
+
+           memset(xi->xi_pix, 0, xi->xi_image->bytes_per_line *
+                  height);
+           break;
+    }
+
+    /* Calculate luminance tables if we need them */
+
+    switch (xi->xi_flags & FLG_VMASK) {
+       case FLG_VG8:
+       case FLG_VS1:
+           if (!lumdone) {
+               int i;
+               unsigned long r, g, b;
+
+               /* This is an integer arithmetic version of YUV to RGB
+                * conversion where we're multiplying by three
+                * coefficients (0.299, 0.587, 0.114) for 24-bit
+                * integers.  See http://en.wikipedia.org/wiki/YUV for
+                * more details.
+                *
+                * NOTE: Using an addition method to build up the
+                * luminance ramp instead of multiplication because
+                * it's probably faster and avoids a gcc 4.8.1
+                * aggressive optimization bug.
+                */
+               for (i = r = g = b = 0; i < 256; i++, r += 5016388, g += 
9848226, b += 1912603) {
+                   rlumtbl[i] = r;
+                   glumtbl[i] = g;
+                   blumtbl[i] = b;
+               }
+               lumdone = 1;
+           }
+    }
+
+    return 0;
+}
+
+
+/*
+ * This routine is called when ever the framebuffer is updated OR when
+ * there is an expose event generated by the X server.
+ *
+ * The X server world is confusing because XDR is NOT done for client
+ * or server, thus leaving each client responsible for getting a X
+ * pixel map prepared in the correct lay out.
+ *
+ * There are something like 18 different visuals and 2 endians that we
+ * need to deal with 1-bit, 2-bit, 4-bit and 8-bit monochrome 8-bit
+ * CLUT, 8-bit True Color, 8-bit Direct Color 15-bit Pseudo Color,
+ * 15-bit True Color, 15-bit Direct color 16-bit Pseudo Color, 16-bit
+ * True Color, 16-bit Direct Color 24-bit Pseudo, True and Direct and
+ * finally 32-bit Pseudo, True and Direct colors.
+ *
+ * For the 1-8 bit case we do some dithering and get an image up as
+ * best we can.  for the >8 bit cases we need to do a bit more.
+ *
+ * Our input is always in RGB (24 bit) order in memory so there is
+ * nothing fancy we need to do there.
+ *
+ * For output, the X server tells us, in an opaque object that we are
+ * not suppose to peek into, where the RGB components go in a BIG
+ * endian bit vector and how many bits per component.  Using this
+ * information we construct masks and shift counts for each component.
+ * This information is later used to construct a bit vector in a
+ * register.  This register is then clocked out as bytes in the
+ * correct ordering.
+ *
+ * x_1, y_1->w, h describes a Rectangle of changed bits (image space coord.)
+ */
+HIDDEN void
+X24_blit(struct fb *ifp, int x_1, int y_1, int w, int h, int flags /* BLIT_xxx 
flags */)
+{
+    struct xinfo *xi = XI(ifp);
+
+    int x2 = x_1 + w - 1;      /* Convert to rectangle corners */
+    int y2 = y_1 + h - 1;
+
+    int x_1wd, x2wd, y_1ht, y2ht;
+    int x, y;
+    int ox, oy;
+    int xdel, ydel;
+    int xwd, xht;
+
+    /*
+     * Newish code, discover masks and shifts for each of RGB
+     *
+     * The Masks are right justified, we just shift them up 6 bits in
+     * the long to give us some room on the low end.  We'll correct
+     * this out later.
+     */
+    unsigned int a_pixel;
+
+    unsigned long test_mask;
+    unsigned long a_mask;
+
+    int red_shift, green_shift, blue_shift;
+    unsigned int mask_red = xi->xi_image->red_mask << 6;
+    unsigned int mask_green = xi->xi_image->green_mask << 6;
+    unsigned int mask_blue = xi->xi_image->blue_mask << 6;
+    size_t i;
+
+    FB_CK_FB(ifp->i);
+
+    /*
+     * Now that we know the mask, we shift a bit left, one bit at a
+     * time until it overlaps the mask.  This tells us how far we have
+     * to shift our pixel to get it under the bit mask.
+     */
+    a_mask = mask_red;
+    test_mask = 1;
+    for (i=0; i<sizeof(unsigned long)*8;i++) {
+       if (test_mask & a_mask) break;
+       test_mask = test_mask << 1;
+    }
+    for (;i<sizeof(unsigned long)*8;i++) {
+       if (!(test_mask & a_mask)) break;
+       test_mask = test_mask << 1;
+    }
+    red_shift = i-8;
+
+    a_mask = mask_green;
+    test_mask = 1;
+    for (i=0; i<sizeof(unsigned long)*8;i++) {
+       if (test_mask & a_mask) break;
+       test_mask = test_mask << 1;
+    }
+    for (;i<sizeof(unsigned long)*8;i++) {
+       if (!(test_mask & a_mask)) break;
+       test_mask = test_mask << 1;
+    }
+    green_shift = i-8;
+
+    a_mask = mask_blue;
+    test_mask = 1;
+    for (i=0; i<sizeof(unsigned long)*8;i++) {
+       if (test_mask & a_mask) break;
+       test_mask = test_mask << 1;
+    }
+    for (;i<sizeof(unsigned long)*8;i++) {
+       if (!(test_mask & a_mask)) break;
+       test_mask =test_mask << 1;
+    }
+    blue_shift = i-8;
+
+    /*
+     * If the changed rectangle is outside the displayed one, there's
+     * nothing to do
+     */
+
+    if (x_1 > xi->xi_irt ||
+       x2 < xi->xi_ilf ||
+       y_1 > xi->xi_itp ||
+       y2 < xi->xi_ibt)
+       return;
+
+    /*
+     * Clamp to actual displayed portion of image
+     */
+    if (x_1 < xi->xi_ilf) x_1 = xi->xi_ilf;
+    if (x2 > xi->xi_irt) x2 = xi->xi_irt;
+    if (y_1 < xi->xi_ibt) y_1 = xi->xi_ibt;
+    if (y2 > xi->xi_itp) y2 = xi->xi_itp;
+
+    /*
+     * Figure out sizes of outermost image pixels
+     */
+    x_1wd = (x_1 == xi->xi_ilf) ? xi->xi_ilf_w : ifp->i->if_xzoom;
+    x2wd = (x2 == xi->xi_irt) ? xi->xi_irt_w : ifp->i->if_xzoom;
+    y_1ht = (y_1 == xi->xi_ibt) ? xi->xi_ibt_h : ifp->i->if_yzoom;
+    y2ht = (y2 == xi->xi_itp) ? xi->xi_itp_h : ifp->i->if_yzoom;
+
+    /* Compute ox: offset from left edge of window to left pixel */
+
+    xdel = x_1 - xi->xi_ilf;
+    if (xdel) {
+       ox = x_1wd + ((xdel - 1) * ifp->i->if_xzoom) + xi->xi_xlf;
+    } else {
+       ox = xi->xi_xlf;
+    }
+
+
+    /* Compute oy: offset from top edge of window to bottom pixel */
+
+    ydel = y_1 - xi->xi_ibt;
+    if (ydel) {
+       oy = xi->xi_xbt - (y_1ht + ((ydel - 1) * ifp->i->if_yzoom));
+    } else {
+       oy = xi->xi_xbt;
+    }
+
+
+    /* Figure out size of changed area on screen in X pixels */
+
+    if (x2 == x_1) {
+       xwd = x_1wd;
+    } else {
+       xwd = x_1wd + x2wd + ifp->i->if_xzoom * (x2 - x_1 - 1);
+    }
+
+    if (y2 == y_1) {
+       xht = y_1ht;
+    } else {
+       xht = y_1ht + y2ht + ifp->i->if_yzoom * (y2 - y_1 - 1);
+    }
+
+    /*
+     * Set pointers to start of source and destination areas; note
+     * that we're going from lower to higher image coordinates, so
+     * irgb increases, but since images are in quadrant I and X uses
+     * quadrant IV, opix _decreases_.
+     */
+
+    switch (xi->xi_flags & FLG_VMASK) {
+       case FLG_VD24:
+       case FLG_VT24:
+       case FLG_VD16:
+       case FLG_VT16:
+           {
+               unsigned char *irgb;
+               unsigned char *opix;
+               unsigned char *red = xi->xi_redmap;
+               unsigned char *grn = xi->xi_grnmap;
+               unsigned char *blu = xi->xi_blumap;
+
+               /*
+                * Calculate the beginning of the line where we are going
+                * to be outputting pixels.
+                */
+               opix = &(xi->xi_pix[oy * xi->xi_image->bytes_per_line + ox * 
(xi->xi_image->bits_per_pixel/8)]);
+
+               /*
+                * Our source of pixels in packed RGB order
+                */
+               irgb = &(xi->xi_mem[(y_1 * xi->xi_iwidth + x_1) * 
sizeof(RGBpixel)]);
+
+               /* General case, zooming in effect */
+
+               for (y = y_1; y <= y2; y++) {
+                   unsigned char *line_irgb;
+                   unsigned char *p;
+
+                   /* Save pointer to start of line */
+
+                   line_irgb = irgb;
+                   p = (unsigned char *)opix;
+
+                   /* For the first line, convert/copy pixels */
+
+                   for (x = x_1; x <= x2; x++) {
+                       int pxwd;
+
+                       /* Calculate # pixels needed */
+                       /* See comment above for more info */
+
+                       if (x == x_1) {
+                           pxwd = x_1wd;
+                       } else if (x == x2) {
+                           pxwd = x2wd;
+                       } else {
+                           pxwd = ifp->i->if_xzoom;
+                       }
+
+                       /*
+                        * Construct a pixel with the color components
+                        * in the right places as described by the
+                        * X servers red, green and blue masks.
+                        */
+                       if (xi->xi_flags & (FLG_XCMAP | FLG_LINCMAP)) {
+                           a_pixel  = (line_irgb[RED] << red_shift) & mask_red;
+                           a_pixel |= (line_irgb[GRN] << green_shift) & 
mask_green;
+                           a_pixel |= (line_irgb[BLU] << blue_shift) & 
mask_blue;
+                       } else {
+                           a_pixel  = (red[line_irgb[RED]] << red_shift) & 
mask_red;
+                           a_pixel |= (grn[line_irgb[GRN]] << green_shift) & 
mask_green;
+                           a_pixel |= (blu[line_irgb[BLU]] << blue_shift) & 
mask_blue;
+                       }
+                       /* take out the safety put in above. */
+                       a_pixel = a_pixel >> 6;
+
+                       /*
+                        * Now we clock out that pixel according to
+                        * the number of bytes AND the byte ordering
+                        *
+                        * A slightly faster version would unroll
+                        * these loops into a number of different
+                        * loops.
+                        *
+                        * The while loop on the inside causes pixel
+                        * replication for when we are zoomed.
+                        */
+                       if (ImageByteOrder(xi->xi_dpy) == MSBFirst) {
+                           if (xi->xi_image->bits_per_pixel == 16) {
+                               while (pxwd--) {
+                                   *p++ = (a_pixel >> 8) & 0xff;
+                                   *p++ = a_pixel & 0xff;
+                               }
+                           } else if (xi->xi_image->bits_per_pixel == 24) {
+                               while (pxwd--) {
+                                   *p++ = (a_pixel >> 16) & 0xff;
+                                   *p++ = (a_pixel >> 8) & 0xff;
+                                   *p++ = a_pixel & 0xff;
+                               }
+                           } else if (xi->xi_image->bits_per_pixel == 32) {
+                               while (pxwd--) {
+                                   *p++ = (a_pixel >> 24) & 0xff;
+                                   *p++ = (a_pixel >> 16) & 0xff;
+                                   *p++ = (a_pixel >> 8) & 0xff;
+                                   *p++ = a_pixel & 0xff;
+                               }
+                           }
+
+                       } else {
+                           /* LSB order */
+                           if (xi->xi_image->bits_per_pixel == 16) {
+                               while (pxwd--) {
+                                   *p++ = a_pixel & 0xff;
+                                   *p++ = (a_pixel >> 8) & 0xff;
+                               }
+                           } else if (xi->xi_image->bits_per_pixel == 24) {
+                               while (pxwd--) {
+                                   *p++ = a_pixel & 0xff;
+                                   *p++ = (a_pixel >> 8) & 0xff;
+                                   *p++ = (a_pixel >> 16) & 0xff;
+                               }
+                           } else if (xi->xi_image->bits_per_pixel == 32) {
+                               while (pxwd--) {
+                                   *p++ = a_pixel & 0xff;
+                                   *p++ = (a_pixel >> 8) & 0xff;
+                                   *p++ = (a_pixel >> 16) & 0xff;
+                                   *p++ = (a_pixel >> 24) & 0xff;
+                               }
+                           }
+
+                       }
+                       /*
+                        * Move to the next input line.
+                        */
+                       line_irgb += sizeof (RGBpixel);
+                   }
+
+                   /*
+                    * And again, move to the beginning of the next
+                    * line up in the X server.
+                    */
+                   opix -= xi->xi_image->bytes_per_line;
+
+                   irgb += xi->xi_iwidth * sizeof(RGBpixel);
+               }
+               break;
+           }
+
+       case FLG_VP8:
+           {
+               int dmx = ox & 0x7;
+               int dmy = (oy & 0x7) << 3;
+
+               unsigned int r, g, b;
+               unsigned char *red = xi->xi_redmap;
+               unsigned char *grn = xi->xi_grnmap;
+               unsigned char *blu = xi->xi_blumap;
+
+               unsigned char *ip = &(xi->xi_mem[(y_1 * xi->xi_iwidth + x_1) *
+                                                sizeof (RGBpixel)]);
+               unsigned char *op = (unsigned char *) &xi->xi_pix[oy *
+                                                                 xi->xi_xwidth 
+ ox];
+
+
+               if (ifp->i->if_xzoom == 1 && ifp->i->if_yzoom == 1) {
+                   /* Special case if no zooming */
+
+                   int j, k;
+
+                   for (j = y2 - y_1 + 1; j; j--) {
+                       unsigned char *lip;
+                       unsigned char *lop;
+
+                       lip = ip;
+                       lop = op;
+
+                       /* For each line, convert/copy pixels */
+
+                       if (xi->xi_flags & (FLG_XCMAP | FLG_LINCMAP)) {
+                           for (k = x2 - x_1 + 1; k; k--) {
+                               r = lip[RED];
+                               g = lip[GRN];
+                               b = lip[BLU];
+
+                               *lop++ = xi->xi_base +
+                                   xi->xi_ccredtbl[(r << 6) + dmx + dmy] +
+                                   xi->xi_ccgrntbl[(g << 6) + dmx + dmy] +
+                                   xi->xi_ccblutbl[(b << 6) + dmx + dmy];
+
+                               dmx = (dmx + 1) & 0x7;
+                               lip += sizeof (RGBpixel);
+                           }
+                       } else {
+                           for (k = x2 - x_1 + 1; k; k--) {
+                               r = red[lip[RED]];
+                               g = grn[lip[GRN]];
+                               b = blu[lip[BLU]];
+
+                               *lop++ = xi->xi_base +
+                                   xi->xi_ccredtbl[(r << 6) + dmx + dmy] +
+                                   xi->xi_ccgrntbl[(g << 6) + dmx + dmy] +
+                                   xi->xi_ccblutbl[(b << 6) + dmx + dmy];
+
+                               dmx = (dmx + 1) & 0x7;
+                               lip += sizeof (RGBpixel);
+                           }
+                       }
+
+                       ip += xi->xi_iwidth * sizeof (RGBpixel);
+                       op -= xi->xi_image->bytes_per_line;
+                       dmx = ox & 0x7;
+                       dmy = (dmy + 0x38) & 0x38;
+                   }
+               } else {
+                   /* General case */
+
+                   for (y = y_1; y <= y2; y++) {
+                       int pyht;
+                       unsigned char *lip;
+                       unsigned char *lop;
+
+                       /* Calculate # lines needed */
+
+                       if (y == y_1)
+                           pyht = y_1ht;
+                       else if (y == y2)
+                           pyht = y2ht;
+                       else
+                           pyht = ifp->i->if_yzoom;
+
+                       /* For each line, convert/copy pixels */
+
+                       while (pyht--) {
+                           lip = ip;
+                           lop = op;
+
+                           if (xi->xi_flags & (FLG_XCMAP | FLG_LINCMAP)) {
+                               for (x = x_1; x <= x2; x++) {
+                                   int pxwd;
+
+                                   /* Calculate # pixels needed */
+
+                                   if (x == x_1)
+                                       pxwd = x_1wd;
+                                   else if (x == x2)
+                                       pxwd = x2wd;
+                                   else
+                                       pxwd = ifp->i->if_xzoom;
+
+                                   r = lip[RED];
+                                   g = lip[GRN];
+                                   b = lip[BLU];
+
+                                   while (pxwd--) {
+                                       *lop++ = xi->xi_base +
+                                           xi->xi_ccredtbl[(r << 6) + dmx + 
dmy] +
+                                           xi->xi_ccgrntbl[(g << 6) + dmx + 
dmy] +
+                                           xi->xi_ccblutbl[(b << 6) + dmx + 
dmy];
+
+                                       dmx = (dmx + 1) & 0x7;
+                                   }
+
+                                   lip += sizeof (RGBpixel);
+                               }
+                           } else {
+                               for (x = x_1; x <= x2; x++) {
+                                   int pxwd;
+
+                                   /* Calculate # pixels needed */
+
+                                   if (x == x_1)
+                                       pxwd = x_1wd;
+                                   else if (x == x2)
+                                       pxwd = x2wd;
+                                   else
+                                       pxwd = ifp->i->if_xzoom;
+
+                                   r = red[lip[RED]];
+                                   g = grn[lip[GRN]];
+                                   b = blu[lip[BLU]];
+
+                                   while (pxwd--) {
+                                       *lop++ = xi->xi_base +
+                                           xi->xi_ccredtbl[(r << 6) + dmx + 
dmy] +
+                                           xi->xi_ccgrntbl[(g << 6) + dmx + 
dmy] +
+                                           xi->xi_ccblutbl[(b << 6) + dmx + 
dmy];
+
+                                       dmx = (dmx + 1) & 0x7;
+                                   }
+
+                                   lip += sizeof (RGBpixel);
+                               }
+                           }
+
+                           op -= xi->xi_image->bytes_per_line;
+                           dmx = ox & 0x7;
+                           dmy = (dmy + 0x38) & 0x38;
+                       }
+                       ip += xi->xi_iwidth * sizeof (RGBpixel);
+                   }
+               }
+               break;
+           }
+
+       case FLG_VS8:
+       case FLG_VG8:
+           {
+               unsigned int r, g, b;
+               unsigned char *red = xi->xi_redmap;
+               unsigned char *grn = xi->xi_grnmap;
+               unsigned char *blu = xi->xi_blumap;
+
+               unsigned char *ip = &(xi->xi_mem[(y_1 * xi->xi_iwidth + x_1) *
+                                                sizeof (RGBpixel)]);
+               unsigned char *op = (unsigned char *) &xi->xi_pix[oy *
+                                                                 xi->xi_xwidth 
+ ox];
+
+               if (ifp->i->if_xzoom == 1 && ifp->i->if_yzoom == 1) {
+                   /* Special case if no zooming */
+
+                   int j, k;
+
+                   for (j = y2 - y_1 + 1; j; j--) {
+                       unsigned char *lip;
+                       unsigned char *lop;
+
+                       lip = ip;
+                       lop = op;
+
+                       /* For each line, convert/copy pixels */
+
+                       if (xi->xi_flags & (FLG_XCMAP | FLG_LINCMAP)) {
+                           for (k = x2 - x_1 + 1; k; k--) {
+                               r = lip[RED];
+                               g = lip[GRN];
+                               b = lip[BLU];
+
+                               *lop++ = (rlumtbl[r] +
+                                         glumtbl[g] +
+                                         blumtbl[b] +
+                                         8388608) >> 24;
+                               lip += sizeof (RGBpixel);
+                           }
+                       } else {
+                           for (k = x2 - x_1 + 1; k; k--) {
+                               r = red[lip[RED]];
+                               g = grn[lip[GRN]];

@@ 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