Commit 65b42bb8 authored by runge's avatar runge

x11vnc: support colormaps for depths other than 8. xinerama warppointer only...

x11vnc: support colormaps for depths other than 8.  xinerama warppointer only if more than one subscreen.
parent 1983292e
This diff is collapsed.
2008-05-31 Karl Runge <runge@karlrunge.com>
* x11vnc: Improvements to nonstandard indexed color support, e.g.
depths 1, 4, 12, etc. instead of only 8. Only enable xinerama
xwarppointer if there is more than 1 subscreen.
2008-05-07 Karl Runge <runge@karlrunge.com>
* x11vnc: add UltraVNC repeater proxy support. fix to setp gui
mode. -threads is now strongly discouraged. Read PORT= in url.
......
This diff is collapsed.
......@@ -2734,6 +2734,23 @@ void check_gui_inputs(void) {
}
}
static int turn_off_truecolor = 0;
static void turn_off_truecolor_ad(rfbClientPtr client) {
if (turn_off_truecolor) {
rfbLog("turning off truecolor advertising.\n");
screen->serverFormat.trueColour = FALSE;
screen->displayHook = NULL;
screen->serverFormat.redShift = 0;
screen->serverFormat.greenShift = 0;
screen->serverFormat.blueShift = 0;
screen->serverFormat.redMax = 0;
screen->serverFormat.greenMax = 0;
screen->serverFormat.blueMax = 0;
turn_off_truecolor = 0;
}
}
/*
* libvncserver callback for when a new client connects
*/
......@@ -2877,6 +2894,43 @@ enum rfbNewClientAction new_client(rfbClientPtr client) {
check_ncache(1, 0);
}
if (advertise_truecolor && indexed_color) {
int rs = 0, gs = 2, bs = 4;
int rm = 3, gm = 3, bm = 3;
if (bpp >= 24) {
rs = 0, gs = 8, bs = 16;
rm = 255, gm = 255, bm = 255;
} else if (bpp >= 16) {
rs = 0, gs = 5, bs = 10;
rm = 31, gm = 31, bm = 31;
}
rfbLog("advertising truecolor.\n");
if (getenv("ADVERT_BMSHIFT")) {
bm--;
}
client->format.trueColour = TRUE;
client->format.redShift = rs;
client->format.greenShift = gs;
client->format.blueShift = bs;
client->format.redMax = rm;
client->format.greenMax = gm;
client->format.blueMax = bm;
rfbSetTranslateFunction(client);
screen->serverFormat.trueColour = TRUE;
screen->serverFormat.redShift = rs;
screen->serverFormat.greenShift = gs;
screen->serverFormat.blueShift = bs;
screen->serverFormat.redMax = rm;
screen->serverFormat.greenMax = gm;
screen->serverFormat.blueMax = bm;
screen->displayHook = turn_off_truecolor_ad;
turn_off_truecolor = 1;
}
if (unixpw) {
unixpw_in_progress = 1;
unixpw_client = client;
......
......@@ -976,8 +976,8 @@ static rfbCursorPtr pixels2curs(unsigned long *pixels, int w, int h,
first = 0;
}
if (cmap8to24 && cmap8to24_fb && depth == 8) {
if (Bpp == 1) {
if (cmap8to24 && cmap8to24_fb && depth <= 16) {
if (Bpp <= 2) {
Bpp = 4;
}
}
......
......@@ -140,6 +140,11 @@ void print_help(int mode) {
" a colormap histogram. Example: -shiftcmap 240\n"
"-notruecolor For 8bpp displays, force indexed color (i.e. a colormap)\n"
" even if it looks like 8bpp TrueColor (rare problem).\n"
"-advertise_truecolor If the X11 display is indexed color, lie to clients\n"
" when they first connect by telling them it is truecolor.\n"
" To workaround RealVNC: inPF has colourMap but not 8bpp\n"
" Use '-advertise_truecolor reset' to reset client fb too.\n"
"\n"
"-visual n This option probably does not do what you think.\n"
" It simply *forces* the visual used for the framebuffer;\n"
" this may be a bad thing... (e.g. messes up colors or\n"
......@@ -147,8 +152,10 @@ void print_help(int mode) {
" workarounds. n may be a decimal number, or 0x hex.\n"
" Run xdpyinfo(1) for the values. One may also use\n"
" \"TrueColor\", etc. see <X11/X.h> for a list. If the\n"
" string ends in \":m\" then for better or for worse the\n"
" visual depth is forced to be m.\n"
" string ends in \":m\" then for better or for worse\n"
" the visual depth is forced to be m. You may want to\n"
" use -noshm when using this option (so XGetImage may\n"
" automatically translate the pixel data).\n"
"\n"
"-overlay Handle multiple depth visuals on one screen, e.g. 8+24\n"
" and 24+8 overlay visuals (the 32 bits per pixel are\n"
......
......@@ -396,7 +396,8 @@ make_so() {
warn "$tmp still exists."
exit 1
fi
tail +$n1 $0 | head -$dn > $tmp
#tail +$n1 $0 | head -$dn > $tmp
tail -n +$n1 $0 | head -n $dn > $tmp
# compile it to Xdummy.so:
rm -f $SO
......
......@@ -114,6 +114,8 @@ int ping_interval = 0; /* -ping */
int flash_cmap = 0; /* follow installed colormaps */
int shift_cmap = 0; /* ncells < 256 and needs shift of pixel values */
int force_indexed_color = 0; /* whether to force indexed color for 8bpp */
int advertise_truecolor = 0;
int advertise_truecolor_reset = 0;
int cmap8to24 = 0; /* -8to24 */
int xform24to32 = 0; /* -24to32 */
char *cmap8to24_str = NULL;
......
......@@ -89,6 +89,8 @@ extern int ping_interval;
extern int flash_cmap;
extern int shift_cmap;
extern int force_indexed_color;
extern int advertise_truecolor;
extern int advertise_truecolor_reset;
extern int cmap8to24;
extern char *cmap8to24_str;
extern int xform24to32;
......
......@@ -1285,8 +1285,12 @@ void scale_and_mark_rect(int X1, int Y1, int X2, int Y2, int mark) {
if (cmap8to24 && cmap8to24_fb) {
src_fb = cmap8to24_fb;
if (scaling && depth == 8) {
fac = 4;
if (scaling) {
if (depth <= 8) {
fac = 4;
} else if (depth <= 16) {
fac = 2;
}
}
}
dst_fb = rfb_fb;
......
......@@ -79,6 +79,7 @@ int rawfb_vnc_reflect = 0;
*/
#define NCOLOR 256
/* this is only for rawfb */
void set_greyscale_colormap(void) {
int i;
if (! screen) {
......@@ -139,6 +140,8 @@ if (0) fprintf(stderr, "set_hi240_colormap: %s\n", raw_fb_pixfmt);
rfbSetClientColourMaps(screen, 0, 256);
}
/* this is only for rawfb */
void unset_colormap(void) {
if (! screen) {
return;
......@@ -151,35 +154,55 @@ void unset_colormap(void) {
if (0) fprintf(stderr, "unset_colormap: %s\n", raw_fb_pixfmt);
}
/* this is X11 case */
void set_colormap(int reset) {
#if NO_X11
if (!reset) {}
return;
#else
static int init = 1;
static XColor color[NCOLOR], prev[NCOLOR];
static XColor *color = NULL, *prev = NULL;
static int ncolor = 0;
Colormap cmap;
Visual *vis;
int i, ncells, diffs = 0;
if (reset) {
init = 1;
ncolor = 0;
if (screen->colourMap.data.shorts) {
free(screen->colourMap.data.shorts);
screen->colourMap.data.shorts = NULL;
}
if (color) {
free(color);
color = NULL;
}
if (prev) {
free(prev);
prev = NULL;
}
}
if (0) fprintf(stderr, "unset_colormap: %d\n", reset);
if (init) {
screen->colourMap.count = NCOLOR;
if (depth > 8) {
ncolor = 1 << depth;
} else {
ncolor = NCOLOR;
}
screen->colourMap.count = ncolor;
screen->serverFormat.trueColour = FALSE;
screen->colourMap.is16 = TRUE;
screen->colourMap.data.shorts = (unsigned short *)
malloc(3*sizeof(unsigned short) * NCOLOR);
malloc(3*sizeof(unsigned short) * ncolor);
}
if (color == NULL) {
color = (XColor *) calloc(ncolor * sizeof(XColor), 1);
prev = (XColor *) calloc(ncolor * sizeof(XColor), 1);
}
for (i=0; i < NCOLOR; i++) {
for (i=0; i < ncolor; i++) {
prev[i].red = color[i].red;
prev[i].green = color[i].green;
prev[i].blue = color[i].blue;
......@@ -203,15 +226,15 @@ if (0) fprintf(stderr, "unset_colormap: %d\n", reset);
}
}
if (ncells != NCOLOR) {
if (init && ! quiet) {
rfbLog("set_colormap: number of cells is %d "
"instead of %d.\n", ncells, NCOLOR);
}
if (ncells != ncolor) {
if (! shift_cmap) {
screen->colourMap.count = ncells;
}
}
if (init && ! quiet) {
rfbLog("set_colormap: number of cells: %d, "
"ncolor(%d) is %d.\n", ncells, depth, ncolor);
}
if (flash_cmap && ! init) {
XWindowAttributes attr;
......@@ -233,9 +256,9 @@ if (0) fprintf(stderr, "unset_colormap: %d\n", reset);
}
}
}
if (ncells > NCOLOR && ! quiet) {
if (ncells > ncolor && ! quiet) {
rfbLog("set_colormap: big problem: ncells=%d > %d\n",
ncells, NCOLOR);
ncells, ncolor);
}
if (vis->class == TrueColor || vis->class == DirectColor) {
......@@ -245,7 +268,7 @@ if (0) fprintf(stderr, "unset_colormap: %d\n", reset);
* mentioned in xdpyinfo. Looks OK... perhaps fortuitously.
*/
if (ncells == 8 && ! shift_cmap) {
ncells = NCOLOR;
ncells = ncolor;
}
}
......@@ -271,7 +294,7 @@ if (0) fprintf(stderr, "unset_colormap: %d\n", reset);
diffs++;
}
if (shift_cmap && k >= 0 && k < NCOLOR) {
if (shift_cmap && k >= 0 && k < ncolor) {
/* kludge to copy the colors to higher pixel values */
screen->colourMap.data.shorts[k*3+0] = color[i].red;
screen->colourMap.data.shorts[k*3+1] = color[i].green;
......@@ -285,7 +308,7 @@ if (0) fprintf(stderr, "unset_colormap: %d\n", reset);
"with uninitialized clients.\n");
}
if (shift_cmap) {
rfbSetClientColourMaps(screen, 0, NCOLOR);
rfbSetClientColourMaps(screen, 0, ncolor);
} else {
rfbSetClientColourMaps(screen, 0, ncells);
}
......@@ -297,7 +320,8 @@ if (0) fprintf(stderr, "unset_colormap: %d\n", reset);
static void debug_colormap(XImage *fb) {
static int debug_cmap = -1;
int i, k, histo[NCOLOR];
int i, k, *histo;
int ncolor;
if (debug_cmap < 0) {
if (getenv("DEBUG_CMAP") != NULL) {
......@@ -312,11 +336,13 @@ static void debug_colormap(XImage *fb) {
if (! fb) {
return;
}
if (fb->bits_per_pixel > 8) {
if (fb->bits_per_pixel > 16) {
return;
}
ncolor = screen->colourMap.count;
histo = (int *) calloc(ncolor * sizeof(int), 1);
for (i=0; i < NCOLOR; i++) {
for (i=0; i < ncolor; i++) {
histo[i] = 0;
}
for (k = 0; k < fb->width * fb->height; k++) {
......@@ -327,7 +353,7 @@ static void debug_colormap(XImage *fb) {
histo[n]++;
}
fprintf(stderr, "\nColormap histogram for current screen contents:\n");
for (i=0; i < NCOLOR; i++) {
for (i=0; i < ncolor; i++) {
unsigned short r = screen->colourMap.data.shorts[i*3+0];
unsigned short g = screen->colourMap.data.shorts[i*3+1];
unsigned short b = screen->colourMap.data.shorts[i*3+2];
......@@ -338,6 +364,7 @@ static void debug_colormap(XImage *fb) {
fprintf(stderr, "\n");
}
}
free(histo);
fprintf(stderr, "\n");
}
......@@ -1931,12 +1958,38 @@ XImage *initialize_xdisplay_fb(void) {
if (xform24to32) {
if (DefaultDepth(dpy, scr) == 24) {
vis_str = strdup("TrueColor:32");
rfbLog("initialize_xdisplay_fb: vis_str set to: %s ",
rfbLog("initialize_xdisplay_fb: vis_str set to: %s\n",
vis_str);
visual_id = (VisualID) 0;
visual_depth = 0;
set_visual_str_to_something = 1;
}
} else if (DefaultDepth(dpy, scr) < 8) {
/* check very low bpp case, e.g. mono or vga16 */
Screen *s = DefaultScreenOfDisplay(dpy);
XImage *xi = XGetImage_wr(dpy, DefaultRootWindow(dpy), 0, 0, 2, 2, AllPlanes,
ZPixmap);
if (xi && xi->bits_per_pixel < 8) {
int lowbpp = xi->bits_per_pixel;
if (!vis_str) {
char tmp[32];
sprintf(tmp, "0x%x:8", (int) s->root_visual->visualid);
vis_str = strdup(tmp);
rfbLog("initialize_xdisplay_fb: low bpp[%d], vis_str "
"set to: %s\n", lowbpp, vis_str);
}
if (using_shm) {
using_shm = 0;
rfbLog("initialize_xdisplay_fb: low bpp[%d], "
"disabling shm\n", lowbpp);
}
visual_id = (VisualID) 0;
visual_depth = 0;
set_visual_str_to_something = 1;
}
if (xi) {
XDestroyImage(xi);
}
}
if (vis_str != NULL) {
......@@ -2420,13 +2473,13 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
" bpp != 32 with depth == 24\n");
cmap8to24 = 0;
}
} else if (depth == 8) {
} else if (depth <= 16) {
/* need to cook up the screen fb to be depth 24 */
fb_bpp = 32;
fb_depth = 24;
} else {
if (!quiet) rfbLog("disabling -8to24 mode:"
" default depth not 24 or 8\n");
" default depth not 16 or less\n");
cmap8to24 = 0;
}
}
......@@ -2489,9 +2542,14 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
}
#endif
if (cmap8to24 && depth == 8) {
rfb_bytes_per_line *= 4;
rot_bytes_per_line *= 4;
if (cmap8to24) {
if (depth <= 8) {
rfb_bytes_per_line *= 4;
rot_bytes_per_line *= 4;
} else if (depth <= 16) {
rfb_bytes_per_line *= 2;
rot_bytes_per_line *= 2;
}
}
/*
......@@ -2596,7 +2654,7 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
have_masks = 0;
}
if (cmap8to24 && depth == 8 && dpy) {
if (cmap8to24 && depth <= 16 && dpy) {
XVisualInfo vinfo;
vinfo.red_mask = 0;
vinfo.green_mask = 0;
......@@ -2638,13 +2696,14 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
free(fmt);
}
if (! have_masks && screen->serverFormat.bitsPerPixel == 8
if (! have_masks && screen->serverFormat.bitsPerPixel <= 16
&& dpy && CellsOfScreen(ScreenOfDisplay(dpy, scr))) {
/* indexed color */
/* indexed color. we let 1 <= bpp <= 16, but it is normally 8 */
if (!quiet) {
rfbLog("\n");
rfbLog("X display %s is 8bpp indexed color\n",
DisplayString(dpy));
rfbLog("X display %s is %dbpp indexed color, depth=%d\n",
DisplayString(dpy), screen->serverFormat.bitsPerPixel,
screen->serverFormat.depth);
if (! flash_cmap && ! overlay) {
rfbLog("\n");
rfbLog("In 8bpp PseudoColor mode if you "
......@@ -2656,6 +2715,18 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
rfbLog("\n");
}
}
if (screen->serverFormat.depth < 8) {
rfbLog("resetting serverFormat.depth %d -> 8.\n",
screen->serverFormat.depth);
rfbLog("resetting serverFormat.bpp %d -> 8.\n",
screen->serverFormat.bitsPerPixel);
screen->serverFormat.depth = 8;
screen->serverFormat.bitsPerPixel = 8;
}
if (screen->serverFormat.depth > 8) {
rfbLog("WARNING: indexed color depth > 8, Tight encoding will crash.\n");
}
screen->serverFormat.trueColour = FALSE;
indexed_color = 1;
set_colormap(1);
......@@ -2688,6 +2759,29 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
indexed_color = 0;
if (!have_masks) {
int M, B = bits_per_color;
if (3*B > fb_bpp) B--;
if (B < 1) B = 1;
M = (1 << B) - 1;
rfbLog("WARNING: all TrueColor RGB masks are zero!\n");
rfbLog("WARNING: cooking something up for VNC fb... B=%d M=%d\n", B, M);
main_red_mask = M;
main_green_mask = M;
main_blue_mask = M;
main_red_mask = main_red_mask << (2*B);
main_green_mask = main_green_mask << (1*B);
main_blue_mask = main_blue_mask << (0*B);
fprintf(stderr, " red_mask: 0x%08lx %s\n", main_red_mask,
bitprint(main_red_mask, 32));
fprintf(stderr, " green_mask: 0x%08lx %s\n", main_green_mask,
bitprint(main_green_mask, 32));
fprintf(stderr, " blue_mask: 0x%08lx %s\n", main_blue_mask,
bitprint(main_blue_mask, 32));
}
/* convert masks to bit shifts and max # colors */
if (main_red_mask) {
while (! (main_red_mask
......@@ -2821,8 +2915,10 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
if (cmap8to24) {
int n = main_bytes_per_line * fb->height;
if (depth == 8) {
if (depth <= 8) {
n *= 4;
} else if (depth <= 16) {
n *= 2;
}
cmap8to24_fb = (char *) malloc(n);
memset(cmap8to24_fb, 0, n);
......
......@@ -790,8 +790,10 @@ static void draw_box(int x, int y, int w, int h, int restore) {
if (cmap8to24 && cmap8to24_fb) {
use_fb = cmap8to24_fb;
pixelsize = 4;
if (depth == 8) {
if (depth <= 8) {
use_Bpl *= 4;
} else if (depth <= 16) {
use_Bpl *= 2;
}
}
......@@ -1882,9 +1884,14 @@ if (0 || debug_scroll > 1) fprintf(stderr, "<<<-rfbDoCopyRect req: %d mod: %d cp
}
}
if (0) fprintf(stderr, "copyrect: cmap8to24_fb: mode=%d\n", mode);
if (cmap8to24 && depth == 8) {
Bpp = 4 * Bpp0;
stride = 4 * stride0;
if (cmap8to24) {
if (depth <= 8) {
Bpp = 4 * Bpp0;
stride = 4 * stride0;
} else if (depth <= 16) {
Bpp = 2 * Bpp0;
stride = 2 * stride0;
}
}
dst = cmap8to24_fb + y1*stride + x1*Bpp;
src = cmap8to24_fb + (y1-dy)*stride + (x1-dx)*Bpp;
......@@ -3566,6 +3573,17 @@ void check_fixscreen(void) {
didfull = 1;
}
}
if (advertise_truecolor && advertise_truecolor_reset && indexed_color) {
/* this will reset framebuffer to correct colors, if needed */
static dlast = 0.0;
now = dnow();
if (now > last_client + 1.0 && now < last_client + 3.0 && now > dlast + 5.0) {
rfbLog("advertise truecolor reset framebuffer\n");
do_new_fb(1);
dlast = dnow();
return;
}
}
}
static int wireframe_mod_state() {
......@@ -8083,8 +8101,12 @@ void scale_mark_xrootpmap(void) {
if (cmap8to24 && cmap8to24_fb) {
src_fb = cmap8to24_fb;
if (scaling && depth == 8) {
fac = 4;
if (scaling) {
if (depth <= 8) {
fac = 4;
} else if (depth <= 16) {
fac = 2;
}
}
}
dst_fb = rfb_fb;
......
......@@ -2,7 +2,7 @@
.TH X11VNC "1" "May 2008" "x11vnc " "User Commands"
.SH NAME
x11vnc - allow VNC connections to real X11 displays
version: 0.9.4, lastmod: 2008-05-10
version: 0.9.4, lastmod: 2008-05-31
.SH SYNOPSIS
.B x11vnc
[OPTION]...
......@@ -161,6 +161,13 @@ a colormap histogram. Example: \fB-shiftcmap\fR 240
For 8bpp displays, force indexed color (i.e. a colormap)
even if it looks like 8bpp TrueColor (rare problem).
.PP
\fB-advertise_truecolor\fR
.IP
If the X11 display is indexed color, lie to clients
when they first connect by telling them it is truecolor.
To workaround RealVNC: inPF has colourMap but not 8bpp
Use '-advertise_truecolor reset' to reset client fb too.
.PP
\fB-visual\fR \fIn\fR
.IP
This option probably does not do what you think.
......@@ -172,8 +179,10 @@ Run
.IR xdpyinfo (1)
for the values. One may also use
"TrueColor", etc. see <X11/X.h> for a list. If the
string ends in ":m" then for better or for worse the
visual depth is forced to be m.
string ends in ":m" then for better or for worse
the visual depth is forced to be m. You may want to
use \fB-noshm\fR when using this option (so XGetImage may
automatically translate the pixel data).
.PP
\fB-overlay\fR
.IP
......
......@@ -2514,6 +2514,17 @@ int main(int argc, char* argv[]) {
shift_cmap = atoi(argv[++i]);
} else if (!strcmp(arg, "-notruecolor")) {
force_indexed_color = 1;
} else if (!strcmp(arg, "-advertise_truecolor")) {
advertise_truecolor = 1;
if (i < argc-1) {
char *s = argv[i+1];
if (s[0] != '-') {
if (strstr(s, "reset")) {
advertise_truecolor_reset = 1;
}
i++;
}
}
} else if (!strcmp(arg, "-overlay")) {
overlay = 1;
} else if (!strcmp(arg, "-overlay_nocursor")) {
......
......@@ -15,7 +15,7 @@ int xtrap_base_event_type = 0;
int xdamage_base_event_type = 0;
/* date +'lastmod: %Y-%m-%d' */
char lastmod[] = "0.9.4 lastmod: 2008-05-10";
char lastmod[] = "0.9.4 lastmod: 2008-05-31";
/* X display info */
......
......@@ -263,19 +263,19 @@ static void initialize_xinerama (void) {
rfbLog("\n");
rfbLog("Xinerama is present and active (e.g. multi-head).\n");
if (! use_xwarppointer && ! got_noxwarppointer) {
rfbLog("Xinerama: enabling -xwarppointer mode to try to correct\n");
rfbLog("Xinerama: mouse pointer motion. XTEST+XINERAMA bug.\n");
rfbLog("Xinerama: Use -noxwarppointer to force XTEST.\n");
use_xwarppointer = 1;
}
/* n.b. change to XineramaGetData() someday */
xineramas = XineramaQueryScreens(dpy, &n);
if (verbose) {
rfbLog("Xinerama: number of sub-screens: %d\n", n);
}
if (! use_xwarppointer && ! got_noxwarppointer && n > 1) {
rfbLog("Xinerama: enabling -xwarppointer mode to try to correct\n");
rfbLog("Xinerama: mouse pointer motion. XTEST+XINERAMA bug.\n");
rfbLog("Xinerama: Use -noxwarppointer to force XTEST.\n");
use_xwarppointer = 1;
}
if (n == 1) {
if (verbose) {
rfbLog("Xinerama: no blackouts needed (only one"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment