Commit 8aa6fb95 authored by runge's avatar runge

x11vnc: first pass at client-side caching, -ncache option.

parent 399a175f
2006-12-17 Karl Runge <runge@karlrunge.com>
* x11vnc: first pass at client-side caching, -ncache option.
have -http guess ../classes/.. to run out of build area.
2006-12-17 Karl Runge <runge@karlrunge.com>
* x11vnc: make -xwarppointer the default if xinerama is active.
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -2014,6 +2014,32 @@ void print_help(int mode) {
" text selection, and some menu traversals. It overrides\n"
" any -pointer_mode setting.\n"
"\n"
#ifndef NO_NCACHE
"-ncache n Client-side caching scheme. Framebuffer memory \"n\"\n"
" (an integer) times that of the full display is allocated\n"
" below the actual framebuffer to cache screen contents\n"
" for rapid retrieval. So a W x H frambuffer is expanded\n"
" to a W x (n+1)*H one. Use 0 to disable. Default: XXX.\n"
"\n"
" This is an experimental option, currently implemented\n"
" in an awkward way in that in the VNC Viewer you can\n"
" see the cache contents if you scroll down, etc. So you\n"
" will have to set things up so you can't see that region.\n"
" If this method is successful, the changes required for\n"
" clients to do this less awkwardly will be investigated.\n"
"\n"
" Note that this mode consumes a lot of memory, both\n"
" on the x11vnc server side and on the VNC Viewer side.\n"
" If n=2 then the amount of RAM used is roughly tripled\n"
" for both x11vnc and the VNC Viewer. As a rule of\n"
" thumb, note that 1280x1024 at depth 24 is about 5MB of\n"
" pixel data.\n"
"\n"
" Because of the way window backingstore and saveunders\n"
" are implemented, n must be even. It will be incremented\n"
" by 1 if it is not.\n"
"\n"
#endif
"-wireframe [str] Try to detect window moves or resizes when a mouse\n"
"-nowireframe button is held down and show a wireframe instead of\n"
" the full opaque window. This is based completely on\n"
......
......@@ -193,6 +193,9 @@ char *wireframe_copyrect_default = "never";
int wireframe_in_progress = 0;
int wireframe_local = 1;
int ncache = 0;
int ncache0 = 0;
/* T+B+L+R,tkey+presist_key,tmouse+persist_mouse */
char *scroll_copyrect_str = NULL;
#ifndef SCROLL_COPYRECT
......
......@@ -155,6 +155,9 @@ extern char *wireframe_copyrect;
extern char *wireframe_copyrect_default;
extern int wireframe_in_progress;
extern int ncache;
extern int ncache0;
extern char *scroll_copyrect_str;
extern char *scroll_copyrect;
extern char *scroll_copyrect_default;
......
......@@ -25,6 +25,7 @@
#include "selection.h"
#include "unixpw.h"
#include "uinput.h"
#include "userinput.h"
int send_remote_cmd(char *cmd, int query, int wait);
int do_remote_query(char *remote_cmd, char *query_cmd, int remote_sync,
......@@ -335,6 +336,13 @@ int check_httpdir(void) {
} else {
snprintf(httpdir, len, "%s/../share/x11vnc/classes", prog);
}
if (stat(httpdir, &sbuf) != 0) {
if (use_openssl || use_stunnel || http_ssl) {
snprintf(httpdir, len, "%s/../classes/ssl", prog);
} else {
snprintf(httpdir, len, "%s/../classes", prog);
}
}
free(prog);
if (stat(httpdir, &sbuf) == 0) {
......@@ -749,7 +757,35 @@ char *process_remote_cmd(char *cmd, int stringonly) {
/*
* Maybe add: passwdfile logfile bg rfbauth passwd...
*/
if (!strcmp(p, "stop") || !strcmp(p, "quit") ||
if (strstr(p, "CR:") == p) { /* skip-cmd-list */
/* CR:WxH+X+Y,dx,dy */
int w, h, x, y, dx, dy;
NOTAPP
if (sscanf(p+3, "%dx%d+%d+%d,%d,%d", &w, &h, &x, &y, &dx, &dy) == 6) {
sraRegionPtr r;
rfbLog("rfbDoCopyRect(screen, %d, %d, %d, %d, %d, %d)\n", x, y, x+w, y+h, dx, dy);
r = sraRgnCreateRect(x, y, x+w, y+h);
do_copyregion(r, dx, dy);
fb_push();
sraRgnDestroy(r);
rfbLog("did\n");
} else {
rfbLog("remote_cmd: bad CR string: %s\n", p);
}
} else if (strstr(p, "ncache") == p) { /* skip-cmd-list */
COLON_CHECK("ncache:")
if (query) {
snprintf(buf, bufn, "ans=%s%s%d", p, co, ncache);
goto qry;
}
p += strlen("ncache:");
ncache = atoi(p);
if (ncache % 2 != 0) {
ncache++;
}
rfbLog("remote_cmd: set -ncache %d\n", ncache);
} else if (!strcmp(p, "stop") || !strcmp(p, "quit") ||
!strcmp(p, "exit") || !strcmp(p, "shutdown")) {
NOTAPP
if (client_connect_file) {
......
......@@ -2816,6 +2816,31 @@ static int scan_display(int ystart, int rescan) {
/* grab the horizontal scanline from the display: */
X_LOCK;
#ifndef NO_NCACHE
#if !NO_X11
if (ncache > 0 && dpy) {
/* XXX watch for problems. */
XEvent ev;
int gotone = 0;
if (XCheckTypedEvent(dpy, MapNotify, &ev)) {
gotone = 1;
} else if (XCheckTypedEvent(dpy, UnmapNotify, &ev)) {
gotone = 2;
} else if (XCheckTypedEvent(dpy, CreateNotify, &ev)) {
gotone = 3;
}
if (gotone) {
XPutBackEvent(dpy, &ev);
X_UNLOCK;
fprintf(stderr, "*** SCAN_DISPLAY CHECK_NCACHE/%d *** %d\n", gotone, y);
check_ncache(0);
X_LOCK;
}
}
#endif
#endif
XRANDR_SET_TRAP_RET(-1, "scan_display-set");
copy_image(scanline, 0, y, 0, 0);
XRANDR_CHK_TRAP_RET(-1, "scan_display-chk");
......
......@@ -2033,6 +2033,23 @@ void initialize_screen(int *argc, char **argv, XImage *fb) {
}
}
#ifndef NO_NCACHE
if (ncache > 0) {
char *new_fb;
int sz = fb->height * fb->bytes_per_line;
new_fb = (char *) calloc((size_t) (sz * (1+ncache)), 1);
if (fb->data) {
memcpy(new_fb, fb->data, sz);
free(fb->data);
}
fb->data = new_fb;
fb->height *= (1+ncache);
height *= (1+ncache);
ncache0 = ncache;
}
#endif
if (cmap8to24 && depth == 8) {
rfb_bytes_per_line *= 4;
rot_bytes_per_line *= 4;
......
......@@ -56,6 +56,7 @@ extern char *crypt(const char*, const char *);
#undef UNIXPW_CRYPT
#endif
int white_pixel(void);
void unixpw_screen(int init);
void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init);
void unixpw_accept(char *user);
......@@ -65,7 +66,7 @@ int su_verify(char *user, char *pass, char *cmd, char *rbuf, int *rbuf_size);
int crypt_verify(char *user, char *pass);
int cmd_verify(char *user, char *pass);
static int white(void);
static int text_x(void);
static int text_y(void);
static void set_db(void);
......@@ -89,7 +90,7 @@ static int char_x = 0, char_y = 0, char_w = 8, char_h = 16;
static int db = 0;
static int white(void) {
int white_pixel(void) {
static unsigned long black_pix = 0, white_pix = 1, set = 0;
RAWFB_RET(0xffffff)
......@@ -162,7 +163,7 @@ void unixpw_screen(int init) {
pscreen = screen;
}
rfbDrawString(pscreen, &default8x16Font, x, y, log, white());
rfbDrawString(pscreen, &default8x16Font, x, y, log, white_pixel());
char_x = x;
char_y = y;
......@@ -1075,13 +1076,13 @@ if (db) fprintf(stderr, "unixpw_verify: '%s' '%s'\n", user, db > 1 ? pass : "***
x = text_x();
y = text_y();
rfbDrawString(pscreen, &default8x16Font, x, y, li, white());
rfbDrawString(pscreen, &default8x16Font, x, y, li, white_pixel());
char_row += 2;
x = text_x();
y = text_y();
rfbDrawString(pscreen, &default8x16Font, x, y, log, white());
rfbDrawString(pscreen, &default8x16Font, x, y, log, white_pixel());
char_col = strlen(log);
......@@ -1245,7 +1246,7 @@ void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) {
x = text_x();
y = text_y();
rfbDrawString(pscreen, &default8x16Font, x, y, pw,
white());
white_pixel());
char_col = strlen(pw);
if (scaling) {
......@@ -1279,7 +1280,7 @@ void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) {
x = text_x();
y = text_y();
rfbDrawString(pscreen, &default8x16Font, x, y,
str, white());
str, white_pixel());
mark_rect_as_modified(x, y-char_h, x+char_w,
y, scaling);
char_col++;
......@@ -1323,7 +1324,7 @@ void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) {
if (db && db <= 2) fprintf(stderr, "u_cnt: %d %d/%d ks: 0x%x '%s'\n", u_cnt, x, y, keysym, keystr);
rfbDrawString(pscreen, &default8x16Font, x, y, keystr, white());
rfbDrawString(pscreen, &default8x16Font, x, y, keystr, white_pixel());
mark_rect_as_modified(x, y-char_h, x+char_w, y, scaling);
char_col++;
......@@ -1555,7 +1556,7 @@ void unixpw_deny(void) {
x = char_x + char_col * char_w;
y = char_y + char_row * char_h;
rfbDrawString(pscreen, &default8x16Font, x, y, pd, white());
rfbDrawString(pscreen, &default8x16Font, x, y, pd, white_pixel());
if (scaling) {
mark_rect_as_modified(0, 0, scaled_x, scaled_y, 1);
} else {
......@@ -1587,7 +1588,7 @@ void unixpw_msg(char *msg, int delay) {
x = char_x + char_col * char_w;
y = char_y + char_row * char_h;
rfbDrawString(pscreen, &default8x16Font, x, y, msg, white());
rfbDrawString(pscreen, &default8x16Font, x, y, msg, white_pixel());
if (scaling) {
mark_rect_as_modified(0, 0, scaled_x, scaled_y, 1);
} else {
......
......@@ -3,6 +3,7 @@
/* -- unixpw.h -- */
extern int white_pixel(void);
extern void unixpw_screen(int init);
extern void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init);
extern void unixpw_accept(char *user);
......
This diff is collapsed.
......@@ -35,5 +35,6 @@ extern int check_xrecord(void);
extern int check_wireframe(void);
extern int fb_update_sent(int *count);
extern int check_user_input(double dt, double dtr, int tile_diffs, int *cnt);
extern void do_copyregion(sraRegionPtr region, int dx, int dy);
#endif /* _X11VNC_USERINPUT_H */
......@@ -15,6 +15,11 @@ typedef struct winattr {
int map_state;
int rx, ry;
double time;
double bs_time;
double su_time;
int bs_x, bs_y, bs_w, bs_h;
int su_x, su_y, su_w, su_h;
int selectinput;
} winattr_t;
#endif /* _X11VNC_WINATTR_T_H */
......@@ -2,7 +2,7 @@
.TH X11VNC "1" "December 2006" "x11vnc " "User Commands"
.SH NAME
x11vnc - allow VNC connections to real X11 displays
version: 0.8.4, lastmod: 2006-12-14
version: 0.8.4, lastmod: 2006-12-17
.SH SYNOPSIS
.B x11vnc
[OPTION]...
......@@ -2376,6 +2376,32 @@ slow setups, but you lose all visual feedback for drags,
text selection, and some menu traversals. It overrides
any \fB-pointer_mode\fR setting.
.PP
\fB-ncache\fR \fIn\fR
.IP
Client-side caching scheme. Framebuffer memory \fIn\fR
(an integer) times that of the full display is allocated
below the actual framebuffer to cache screen contents
for rapid retrieval. So a W x H frambuffer is expanded
to a W x (n+1)*H one. Use 0 to disable. Default: XXX.
.IP
This is an experimental option, currently implemented
in an awkward way in that in the VNC Viewer you can
see the cache contents if you scroll down, etc. So you
will have to set things up so you can't see that region.
If this method is successful, the changes required for
clients to do this less awkwardly will be investigated.
.IP
Note that this mode consumes a lot of memory, both
on the x11vnc server side and on the VNC Viewer side.
If n=2 then the amount of RAM used is roughly tripled
for both x11vnc and the VNC Viewer. As a rule of
thumb, note that 1280x1024 at depth 24 is about 5MB of
pixel data.
.IP
Because of the way window backingstore and saveunders
are implemented, n must be even. It will be incremented
by 1 if it is not.
.PP
\fB-wireframe\fR \fI[str],\fR \fB-nowireframe\fR
.IP
Try to detect window moves or resizes when a mouse
......
......@@ -554,6 +554,7 @@ static void watch_loop(void) {
}
check_new_clients();
check_ncache();
check_xevents(0);
check_autorepeat();
check_pm();
......@@ -611,8 +612,9 @@ static void watch_loop(void) {
if (button_mask && (!show_dragging || pointer_mode == 0)) {
/*
* if any button is pressed do not update rfb
* screen, but do flush the X11 display.
* if any button is pressed in this mode do
* not update rfb screen, but do flush the
* X11 display.
*/
X_LOCK;
XFlush_wr(dpy);
......@@ -1200,6 +1202,7 @@ static void print_settings(int try_http, int bg, char *gui_str) {
fprintf(stderr, " buttonmap: %s\n", pointer_remap
? pointer_remap : "null");
fprintf(stderr, " dragging: %d\n", show_dragging);
fprintf(stderr, " ncache: %d\n", ncache);
fprintf(stderr, " wireframe: %s\n", wireframe_str ?
wireframe_str : WIREFRAME_PARMS);
fprintf(stderr, " wirecopy: %s\n", wireframe_copyrect ?
......@@ -2105,6 +2108,14 @@ int main(int argc, char* argv[]) {
pointer_remap = strdup(argv[++i]);
} else if (!strcmp(arg, "-nodragging")) {
show_dragging = 0;
#ifndef NO_NCACHE
} else if (!strcmp(arg, "-ncache")) {
CHECK_ARGC
ncache = atoi(argv[++i]);
if (ncache % 2 != 0) {
ncache++;
}
#endif
} else if (!strcmp(arg, "-wireframe")
|| !strcmp(arg, "-wf")) {
wireframe = 1;
......
......@@ -134,7 +134,9 @@
#define PASSWD_UNLESS_NOPW 0
#endif
/* these are for delaying features: */
#define xxNO_SSL_OR_UNIXPW
#define xxNO_NCACHE
/*
* Beginning of support for small binary footprint build for embedded
......@@ -360,6 +362,8 @@ extern int button_mask; /* button state and info */
extern int button_mask_prev;
extern int num_buttons;
extern long xselectinput_rootwin;
extern unsigned int display_button_mask;
extern unsigned int display_mod_mask;
......
......@@ -15,7 +15,7 @@ int xtrap_base_event_type = 0;
int xdamage_base_event_type = 0;
/* date +'lastmod: %Y-%m-%d' */
char lastmod[] = "0.8.4 lastmod: 2006-12-14";
char lastmod[] = "0.8.4 lastmod: 2006-12-17";
/* X display info */
......@@ -36,6 +36,8 @@ int button_mask = 0; /* button state and info */
int button_mask_prev = 0;
int num_buttons = -1;
long xselectinput_rootwin = 0;
unsigned int display_button_mask = 0;
unsigned int display_mod_mask = 0;
......
......@@ -107,7 +107,8 @@ static void initialize_xevents(int reset) {
* XXX: does this cause a flood of other stuff?
*/
X_LOCK;
XSelectInput(dpy, rootwin, PropertyChangeMask);
xselectinput_rootwin |= PropertyChangeMask;
XSelectInput(dpy, rootwin, xselectinput_rootwin);
X_UNLOCK;
did_xselect_input = 1;
}
......
......@@ -382,11 +382,17 @@ void push_sleep(int n) {
* try to forcefully push a black screen to all connected clients
*/
void push_black_screen(int n) {
int Lx = dpy_x, Ly = dpy_y;
if (!screen) {
return;
}
zero_fb(0, 0, dpy_x, dpy_y);
mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0);
#ifndef NO_NCACHE
if (ncache > 0) {
Ly = dpy_y * (1+ncache);
}
#endif
zero_fb(0, 0, Lx, Ly);
mark_rect_as_modified(0, 0, Lx, Ly, 0);
push_sleep(n);
}
......@@ -406,13 +412,19 @@ void refresh_screen(int push) {
*/
void zero_fb(int x1, int y1, int x2, int y2) {
int pixelsize = bpp/8;
int line, fill = 0;
int line, fill = 0, yfac = 1;
char *dst;
#ifndef NO_NCACHE
if (ncache > 0) {
yfac = 1+ncache;
}
#endif
if (x1 < 0 || x2 <= x1 || x2 > dpy_x) {
return;
}
if (y1 < 0 || y2 <= y1 || y2 > dpy_y) {
if (y1 < 0 || y2 <= y1 || y2 > yfac * dpy_y) {
return;
}
if (! main_fb) {
......
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