X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fglx%2Fgrab-ximage.c;h=6000e563c7b6bb5fa14a1f030e64bac22b2e0b2c;hp=d1e920794a0acdbdfeeee93153378274fadbdaf4;hb=ffd8c0873576a9e3065696a624dce6b766b77062;hpb=40eacb5812ef7c0e3374fb139afbb4f5bc8bbfb5 diff --git a/hacks/glx/grab-ximage.c b/hacks/glx/grab-ximage.c index d1e92079..6000e563 100644 --- a/hacks/glx/grab-ximage.c +++ b/hacks/glx/grab-ximage.c @@ -16,6 +16,7 @@ #include #include +#include #include #include #include /* only for GLfloat */ @@ -26,6 +27,7 @@ extern char *progname; #include +#include #undef MAX #define MAX(a,b) ((a)>(b)?(a):(b)) @@ -85,16 +87,19 @@ spread_bits (unsigned char value, unsigned char width) } -/* Returns an XImage structure containing an image of the desktop. - (As a side-effect, that image *may* be painted onto the given Window.) - This XImage will be 32 bits per pixel, 8 each per R, G, and B, with the - extra byte set to 0xFF. - */ -XImage * -screen_to_ximage (Screen *screen, Window window) +static Bool +bigendian (void) +{ + union { int i; char c[sizeof(int)]; } u; + u.i = 1; + return !u.c[0]; +} + + +static XImage * +screen_to_ximage_1 (Screen *screen, Window window, Pixmap pixmap) { Display *dpy = DisplayOfScreen (screen); - Pixmap pixmap = 0; XWindowAttributes xgwa; int win_width, win_height; int tex_width, tex_height; @@ -103,9 +108,6 @@ screen_to_ximage (Screen *screen, Window window) win_width = xgwa.width; win_height = xgwa.height; - pixmap = XCreatePixmap(dpy, window, xgwa.width, xgwa.height, xgwa.depth); - load_random_image (screen, window, pixmap); - /* GL texture sizes must be powers of two. */ tex_width = to_pow2(win_width); tex_height = to_pow2(win_height); @@ -146,10 +148,10 @@ screen_to_ximage (Screen *screen, Window window) */ { int x, y; - int crpos, cgpos, cbpos, capos; /* bitfield positions */ - int srpos, sgpos, sbpos; - int srmsk, sgmsk, sbmsk; - int srsiz, sgsiz, sbsiz; + unsigned int crpos=0, cgpos=0, cbpos=0, capos=0; /* bitfield positions */ + unsigned int srpos=0, sgpos=0, sbpos=0; + unsigned int srmsk=0, sgmsk=0, sbmsk=0; + unsigned int srsiz=0, sgsiz=0, sbsiz=0; int i; unsigned char spread_map[3][256]; @@ -171,7 +173,10 @@ screen_to_ximage (Screen *screen, Window window) we need to pack things in "RGBA" order on the client machine, regardless of its endianness. */ - crpos = 0, cgpos = 8, cbpos = 16, capos = 24; + if (bigendian()) + crpos = 24, cgpos = 16, cbpos = 8, capos = 0; + else + crpos = 0, cgpos = 8, cbpos = 16, capos = 24; if (colors == 0) /* truecolor */ { @@ -234,3 +239,92 @@ screen_to_ximage (Screen *screen, Window window) return ximage2; } } + + +/* Returns an XImage structure containing an image of the desktop. + (As a side-effect, that image *may* be painted onto the given Window.) + This XImage will be 32 bits per pixel, 8 each per R, G, and B, with the + extra byte set to 0xFF. + */ +XImage * +screen_to_ximage (Screen *screen, Window window, char **filename_return) +{ + Display *dpy = DisplayOfScreen (screen); + Pixmap pixmap = 0; + XWindowAttributes xgwa; + + XGetWindowAttributes (dpy, window, &xgwa); + pixmap = XCreatePixmap (dpy, window, xgwa.width, xgwa.height, xgwa.depth); + load_random_image (screen, window, pixmap, filename_return); + + return screen_to_ximage_1 (screen, window, pixmap); +} + + +typedef struct { + void (*callback) (Screen *, Window, XImage *, + const char *name, void *closure, double cvt_time); + void *closure; + Pixmap pixmap; +} img_closure; + + +/* Returns the current time in seconds as a double. + */ +static double +double_time (void) +{ + struct timeval now; +# ifdef GETTIMEOFDAY_TWO_ARGS + struct timezone tzp; + gettimeofday(&now, &tzp); +# else + gettimeofday(&now); +# endif + + return (now.tv_sec + ((double) now.tv_usec * 0.000001)); +} + + +static void +img_cb (Screen *screen, Window window, Drawable drawable, + const char *name, void *closure) +{ + XImage *ximage; + double cvt_time = double_time(); + img_closure *data = (img_closure *) closure; + /* copy closure data to stack and free the original before running cb */ + img_closure dd = *data; + memset (data, 0, sizeof (*data)); + free (data); + data = 0; + ximage = screen_to_ximage_1 (screen, window, dd.pixmap); + dd.callback (screen, window, ximage, name, dd.closure, cvt_time); +} + + +/* Like the above, but loads the image in the background and runs the + given callback once it has been loaded. + */ +#include +extern XtAppContext app; + +void +fork_screen_to_ximage (Screen *screen, Window window, + void (*callback) (Screen *, Window, XImage *, + const char *name, + void *closure, + double cvt_time), + void *closure) +{ + Display *dpy = DisplayOfScreen (screen); + XWindowAttributes xgwa; + img_closure *data = (img_closure *) calloc (1, sizeof(*data)); + data->callback = callback; + data->closure = closure; + + XGetWindowAttributes (dpy, window, &xgwa); + data->pixmap = XCreatePixmap (dpy, window, xgwa.width, xgwa.height, + xgwa.depth); + fork_load_random_image (screen, window, data->pixmap, img_cb, data); +}