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