spencer@eecs.umich.edu (Spencer W. Thomas) (05/16/91)
I'm running into very strange behavior from 8-bit DirectColor visuals.
(Test program enclosed below.) Synopsis of problem: DirectColor
colormap entries are not loaded correctly, and the map is not
reinstalled correctly after it has been uninstalled. Some servers
crash.
Has anyone seen this? Is there a fix? (wait for R5?) If you've got a
different configuration from the ones described below, can you try my
program and describe the results? Thanks.
The test procedure is
1. Create a DirectColor colormap, and a window that uses it.
2. Install the colormap (by window manager or program, the result
is the same)
3. Call XAllocColorPlanes to get 2 red, 2 green, and 2 blue
planes.
4. Load values into the colormap (I'm trying to create a 2x2x2
color cube, so I load (0,0,0), (1,1,1), (2,2,2), and
(3,3,3) with "gray" values.) According to the
documentation, this should cause all 64 entries to be
filled.)
5. Uninstall the colormap.
6. Install the colormap.
Test results. Most servers work fine in PseudoColor, but those with
8-bit DirectColor visuals fail in various ways.
DEC 3100, 8-bit color, running MIT X11R4 (I'm not sure which fixes):
Step 2 "blacks out" only the first 8 entries of the colormap.
Step 4 loads exactly 4 colormap entries. (The interesting
thing is that the right thing happens if the visual is
PseudoColor instead of DirectColor.)
Step 6 reloads only the first 8 entries of the colormap with
a 4-entry red ramp and 4 blacks.
More curious behavior: with a GrayScale visual, this still
creates a COLORED map.
DEC 5000-200, 24-bit color, running DECwindows
Works fine. (24-bit DirectColor visual)
Sparcstation 1, 8-bit color, MIT X11R4
Step 4 crashes the server. (It sometimes survives to step 6?)
IBM RS-6000, 8-bit color, IBM X11R3
Step 2 or 3 crashes the server. (Server has PseudoColor only.)
Mac IIx, 8-bit color, Mac X 1.1
Step 4 loads 4 "gray" colormap cells.
Steps 5 and 6 have no effect.
Finally, the program. You might want to run it with no window manager
"in the way", as it does it's own XInstallColormap/XUninstallColormap
(to keep the exact time and sequence of installation controlled).
Compile with
cc -o xcmapbug xcmapbug.c -lX11
Usage:
xcmapbug [-v] [-l] [-d display] [visual]
-v Verbose mode. Prints out colormap contents.
-l Explicitly loads 64 entries instead of the 4 that
"should work".
-d display Display name.
visual Type of visual. Default is PseudoColor. You must
type the full name of the visual type, but case is
irrelevant.
I ran
xcmapbug -v directcolor
=S
: Run this shell script with "sh" not "csh"
PATH=:/bin:/usr/bin:/usr/ucb
export PATH
all=FALSE
if [ $1x = -ax ]; then
all=TRUE
fi
/bin/echo 'Extracting xcmapbug.c'
sed 's/^X//' <<'//go.sysin dd *' >xcmapbug.c
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <ctype.h>
X/* Make Sys V macros map to BSD macros */
#ifndef _tolower
#define _tolower tolower
#define _toupper toupper
#endif
#define COUNT_OF(_array_) ( sizeof (_array_) / sizeof (_array_[0]) )
X/* Build a pixel from RGB values. Note variable name dependencies. */
#define SHIFT_MASK_PIXEL(r, g, b) \
(( (((r)<<rs)&rm ) | (((g)<<gs)&gm) | (((b)<<bs)&bm)) + pixel_base)
char *visual_class_to_string();
int verbose;
main( argc, argv )
char **argv;
{
static int depths[] = { 8, 12, 24 }; /* List of depths to try. */
char *flagp, *display = 0;
Colormap cmap = 0;
Display *dpy;
Window w;
XVisualInfo vi;
int vis_class = PseudoColor;
int depth, i;
XSetWindowAttributes xswa;
unsigned long mask = 0;
int stage = 0;
XEvent ev;
int longflag = 0;
while ( argc-- > 1 ) {
++argv;
if ( **argv == '-' ) {
flagp = *argv;
while ( *++flagp )
switch( *flagp ) {
case 'l': longflag = 1; break;
case 'v': verbose = 1; break;
case 'd': display = *++argv; argc--; break;
}
}
else if ( isdigit( **argv ) )
vis_class = atoi( *argv );
else
vis_class = visual_string_to_class( *argv );
}
if ( !(dpy = XOpenDisplay(display)) ) {
printf( "Can't open display.\n" );
exit(1);
}
/* Look for a matching visual. */
for ( depth = i = 0; i < COUNT_OF(depths); i++ ) {
if ( XMatchVisualInfo( dpy, 0, depths[i], vis_class, &vi ) ) {
depth = depths[i];
break;
}
}
if ( depth == 0 ) {
printf( "No visuals of type %s\n",
visual_class_to_string( vis_class ) );
exit(0);
}
else
printf( "Trying %d-bit visual of type %s\n",
depth, visual_class_to_string( vis_class ) );
xswa.colormap = cmap = XCreateColormap( dpy, DefaultRootWindow( dpy ),
vi.visual, AllocNone );
if ( cmap == 0 ) {
printf( "Unable to create colormap.\n" );
exit(0);
}
mask |= CWColormap;
xswa.event_mask = ButtonPressMask | ExposureMask;
mask |= CWEventMask;
xswa.border_pixel = xswa.background_pixel = 0;
mask |= CWBackPixel | CWBorderPixel;
w = XCreateWindow( dpy, DefaultRootWindow(dpy), 0, 0, 256, 256,
1, depth, InputOutput, vi.visual, mask, &xswa );
XMapRaised( dpy, w );
for (;;) {
XNextEvent( dpy, &ev );
switch( ev.type ) {
case Expose:
draw( dpy, w, &vi );
break;
case ButtonPress:
switch( stage++ ) {
case 0:
/* Important to have cmap installed at this point. */
XInstallColormap( dpy, cmap );
make_map( dpy, cmap, longflag );
printf( "Created colormap.\n" );
break;
case 1:
XUninstallColormap( dpy, cmap );
printf( "Uninstalled colormap.\n" );
break;
case 2:
XInstallColormap( dpy, cmap );
printf( "Reinstalled colormap.\n" );
break;
case 3:
printf( "Bye bye\n" );
exit(0);
/* NOTREACHED */
}
break;
}
}
}
draw( dpy, w, v )
Display *dpy;
Window w;
XXVisualInfo *v;
{
int x, y, c;
GC gc;
unsigned long rm, gm, bm;
int rs, gs, bs, pixel_base = 0;
int depth, rows, cols;
if ( v->depth > 12 )
depth = v->bits_per_rgb;
else
depth = v->depth;
rows = 1 << ((depth + 1) / 2);
cols = 1 << (depth / 2);
/* Assume masks if depth > 12. */
if ( v->depth > 12 ) {
rm = v->red_mask;
rs = shift_match_right( rm );
gm = v->green_mask;
gs = shift_match_right( gm );
bm = v->blue_mask;
bs = shift_match_right( bm );
}
else {
rm = gm = bm = (1 << depth) - 1;
rs = gs = bs = 0;
}
gc = XCreateGC( dpy, w, 0L, (XGCValues *)0 );
for ( c = 0; c < 1 << depth; c++ ) {
x = (256 / cols) * (c % cols);
y = (256 / rows) * (c / cols);
XSetForeground( dpy, gc, SHIFT_MASK_PIXEL(c,c,c) );
XFillRectangle( dpy, w, gc, x, y, 256/cols, 256/rows );
}
}
int
shift_match_right (mask)
unsigned long int mask;
{
register int shift;
register unsigned long int low_bit;
if (mask == 0) return (0);
low_bit = 1;
for (shift = 0; (low_bit & mask) == 0; shift++) {
low_bit <<= 1;
}
return (shift);
}
X/* Create a 2x2x2 color cube. */
make_map( dpy, cmap, longflag )
Display *dpy;
Colormap cmap;
{
int i, j, k, idx;
XColor color_defs[64];
unsigned long int rm, gm, bm, pixel_base;
int rs, gs, bs;
if ( !XAllocColorPlanes( dpy, cmap, 1, &pixel_base,
1, 2, 2, 2, &rm, &gm, &bm ) ) {
printf( "Can't alloc color planes.\n" );
exit(0);
}
rs = shift_match_right(rm);
gs = shift_match_right(gm);
bs = shift_match_right(bm);
if ( verbose )
printf( "Base: %04x Masks: %04x %04x %04x, Shifts: %d %d %d\n",
pixel_base, rm, gm, bm, rs, gs, bs );
/*
* Set up the color map entries.
*/
if ( !longflag )
for (i = 0; i < 4; i++) {
color_defs[i].pixel = SHIFT_MASK_PIXEL(i, i, i) + pixel_base;
color_defs[i].red =
color_defs[i].green =
color_defs[i].blue = (i * 85) << 8;
color_defs[i].flags = DoRed | DoGreen | DoBlue;
if ( verbose )
printf( "Color %04x: %04x %04x %04x\n",
color_defs[i].pixel, color_defs[i].red,
color_defs[i].green, color_defs[i].blue );
}
else
for ( k = 0; k < 4; k++ )
for ( j = 0; j < 4; j++ )
for (i = 0; i < 4; i++) {
idx = i + 4 * (j + 4 * k);
color_defs[idx].pixel = SHIFT_MASK_PIXEL(i, j, k) +
pixel_base;
color_defs[idx].red = (i * 85) << 8;
color_defs[idx].green = (j * 85) << 8;
color_defs[idx].blue = (k * 85) << 8;
color_defs[idx].flags = DoRed | DoGreen | DoBlue;
if ( verbose )
printf( "Color %04x: %04x %04x %04x\n",
color_defs[idx].pixel, color_defs[idx].red,
color_defs[idx].green, color_defs[idx].blue );
}
XStoreColors( dpy, cmap, color_defs, (longflag ? 64 : 4) );
XFlush( dpy );
}
int visual_string_to_class(vis_type)
char *vis_type;
{
static struct {
char *string;
int type;
} visual_type_table[] = {
{ "grayscale", GrayScale},
{ "greyscale", GrayScale},
{ "staticgrey", StaticGray},
{ "staticgray", StaticGray},
{ "staticcolor", StaticColor},
{ "pseudocolor", PseudoColor},
{ "truecolor", TrueColor},
{ "directcolor", DirectColor}
};
int i;
int visual_type = 9999;
char *ptr;
for (ptr = vis_type; *ptr != '\0'; ptr++)
if (isupper(*ptr)) *ptr = _tolower(*ptr);
for (i = 0; i < COUNT_OF(visual_type_table); i++)
if (strcmp (visual_type_table[i].string, vis_type) == 0) {
visual_type = visual_type_table[i].type;
break;
}
return visual_type;
}
char *visual_class_to_string(visual_type)
int visual_type;
{
char *type_string;
switch (visual_type) {
case DirectColor: type_string = "DirectColor"; break;
case PseudoColor: type_string = "PseudoColor"; break;
case TrueColor: type_string = "TrueColor"; break;
case StaticColor: type_string = "StaticColor"; break;
case GrayScale: type_string = "GrayScale"; break;
case StaticGray: type_string = "StaticGray"; break;
default: type_string = "any/unknown"; break;
}
return type_string;
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
/bin/chmod 644 xcmapbug.c
/bin/echo -n ' '; /bin/ls -ld xcmapbug.c
fi
exit
--
=Spencer W. Thomas EECS Dept, U of Michigan, Ann Arbor, MI 48109
spencer@eecs.umich.edu 313-936-2616 (8-6 E[SD]T M-F)rws@expo.lcs.mit.EDU (Bob Scheifler) (05/16/91)
Has anyone seen this?
Yes.
Is there a fix? (wait for R5?)
Yes. (At least, if I can manage to keep Somebody from deleting the code
again between prereleases.)ntakahas@parole.is.tsukuba.ac.jp (TAKAHASHI Naoto) (05/17/91)
In article <SPENCER.91May15152351@spline.eecs.umich.edu> spencer@eecs.umich.edu (Spencer W. Thomas) writes: > Is there a fix? (wait for R5?) If you cannot wait for R5, get my 24-bit colour server for Suns and apply the patch to dix/colormap.c. -- TAKAHASHI Naoto Machine Intelligence Lab., Inst. of Inf. Sci. & Elec., Univ. of Tsukuba 1-1-1 Tennodai, Tsukuba, 305 Japan