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