/* -*- mode: C; tab-width: 4 -*-
- * xscreensaver, Copyright (c) 1992-2014 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1992-2018 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* on wood).
* 08 Oct 1999 Jonas Munsin (jmunsin@iki.fi)
* Corrected several bugs causing references beyond allocated memory.
+ * 09 Oct 2016 Dave Odell (dmo2118@gmail.com)
+ * Updated for new xshm.c.
*/
#include <math.h>
+#include <time.h>
#include "screenhack.h"
/*#include <X11/Xmd.h>*/
-
-#ifdef HAVE_XSHM_EXTENSION
# include "xshm.h"
-#endif /* HAVE_XSHM_EXTENSION */
#define CARD32 unsigned int
#define CARD16 unsigned short
int ***from;
int ****from_array;
int *fast_from;
+ int from_size;
int bpp_size;
-#ifdef HAVE_XSHM_EXTENSION
- Bool use_shm;
XShmSegmentInfo shm_info;
-#endif /* HAVE_XSHM_EXTENSION */
void (*effect) (struct state *, int);
void (*draw) (struct state *, int);
void (*draw_routine) (struct state *st, XImage *, XImage *, int, int, int *);
async_load_state *img_loader;
+ Pixmap pm;
};
;
else if (s && *s)
fprintf(stderr,"%s: bogus effect: %s\n", progname, s);
+ if (s) free (s);
if (st->effect == NULL && st->radius == 0 && st->speed == 0 && st->number == 0
&& !st->blackhole && !st->vortex && !st->magnify && !st->reflect) {
}
}
- /* never allow the radius to be too close to the min window dimension
- */
- if (st->radius > st->xgwa.width * 0.3) st->radius = st->xgwa.width * 0.3;
- if (st->radius > st->xgwa.height * 0.3) st->radius = st->xgwa.height * 0.3;
-
+ if (st->xgwa.width > 2560 || st->xgwa.height > 2560)
+ st->radius *= 2; /* Retina displays */
/* -swamp mode consumes vast amounts of memory, proportional to radius --
so throttle radius to a small-ish value (60 => ~30MB.)
if (st->effect == &swamp_thing && st->radius > 60)
st->radius = 60;
+ /* never allow the radius to be too close to the min window dimension
+ */
+ {
+ int max = (st->xgwa.width > st->xgwa.height
+ ? st->xgwa.height : st->xgwa.width) * 2 / (5 * st->number);
+ if (st->radius > max) st->radius = max;
+ }
+
if (st->delay < 0)
st->delay = 0;
if (st->radius <= 0)
st->dpy = dpy;
st->window = window;
-#ifdef HAVE_XSHM_EXTENSION
- st->use_shm = get_boolean_resource(st->dpy, "useSHM", "Boolean");
-#endif /* HAVE_XSHM_EXTENSION */
-
distort_reset (st);
st->black_pixel = BlackPixelOfScreen( st->xgwa.screen );
gcv.function = GXcopy;
- gcv.subwindow_mode = IncludeInferiors;
gcflags = GCFunction;
- if (use_subwindow_mode_p(st->xgwa.screen, st->window)) /* see grabscreen.c */
- gcflags |= GCSubwindowMode;
st->gc = XCreateGC (st->dpy, st->window, gcflags, &gcv);
+ /* On MacOS X11, XGetImage on a Window often gets an inexplicable BadMatch,
+ possibly due to the window manager having occluded something? It seems
+ nondeterministic. Loading the image into a pixmap instead fixes it. */
+ if (st->pm) XFreePixmap (st->dpy, st->pm);
+ st->pm = XCreatePixmap (st->dpy, st->window,
+ st->xgwa.width, st->xgwa.height, st->xgwa.depth);
+
st->img_loader = load_image_async_simple (0, st->xgwa.screen, st->window,
- st->window, 0, 0);
+ st->pm, 0, 0);
st->start_time = time ((time_t *) 0);
return st;
}
st->start_time = time ((time_t *) 0);
- st->buffer_map = 0;
- st->orig_map = XGetImage(st->dpy, st->window, 0, 0, st->xgwa.width, st->xgwa.height,
- ~0L, ZPixmap);
+ if (! st->pm) abort();
+ XClearWindow (st->dpy, st->window);
+ XCopyArea (st->dpy, st->pm, st->window, st->gc,
+ 0, 0, st->xgwa.width, st->xgwa.height, 0, 0);
+ if (st->orig_map) XDestroyImage (st->orig_map);
+ st->orig_map = XGetImage(st->dpy, st->pm, 0, 0,
+ st->xgwa.width, st->xgwa.height,
+ ~0L, ZPixmap);
+ if (st->buffer_map_cache) free (st->buffer_map_cache);
st->buffer_map_cache = malloc(sizeof(unsigned long)*(2*st->radius+st->speed+2)*(2*st->radius+st->speed+2));
if (st->buffer_map_cache == NULL) {
exit(EXIT_FAILURE);
}
-# ifdef HAVE_XSHM_EXTENSION
-
- if (st->use_shm)
- {
- st->buffer_map = create_xshm_image(st->dpy, st->xgwa.visual, st->orig_map->depth,
- ZPixmap, 0, &st->shm_info,
- 2*st->radius + st->speed + 2,
- 2*st->radius + st->speed + 2);
- if (!st->buffer_map)
- st->use_shm = False;
- }
-# endif /* HAVE_XSHM_EXTENSION */
-
- if (!st->buffer_map)
- {
- st->buffer_map = XCreateImage(st->dpy, st->xgwa.visual,
- st->orig_map->depth, ZPixmap, 0, 0,
- 2*st->radius + st->speed + 2, 2*st->radius + st->speed + 2,
- 8, 0);
- st->buffer_map->data = (char *)
- calloc(st->buffer_map->height, st->buffer_map->bytes_per_line);
- }
+ if (st->buffer_map)
+ destroy_xshm_image (st->dpy, st->buffer_map, &st->shm_info);
+ st->buffer_map = create_xshm_image(st->dpy, st->xgwa.visual, st->orig_map->depth,
+ ZPixmap, &st->shm_info,
+ 2*st->radius + st->speed + 2,
+ 2*st->radius + st->speed + 2);
if ((st->buffer_map->byte_order == st->orig_map->byte_order)
&& (st->buffer_map->depth == st->orig_map->depth)
{
int *p;
int i, j;
+ if (st->fast_from) free (st->fast_from);
st->fast_from = calloc(1, sizeof(int)*((st->buffer_map->bytes_per_line/st->bpp_size)*(2*st->radius+st->speed+2) + 2*st->radius+st->speed+2));
if (st->fast_from == NULL) {
perror("distort");
* then pointers could be used instead of arrays in some places (and
* maybe give a speedup - maybe also consume less memory)
*/
+ if (st->from) {
+ for (i = 0; i < st->from_size; i++)
+ if (st->from[i]) {
+ for (j = 0; j < st->from_size; j++) {
+ if (st->from[i][j]) free (st->from[i][j]);
+ }
+ free (st->from[i]);
+ }
+ free (st->from);
+ }
+ st->from_size = s;
st->from = (int ***)malloc(s*sizeof(int **));
if (st->from == NULL) {
perror("distort");
int k;
if (st->effect == &swamp_thing) {
+ if (st->from_array) free (st->from_array);
st->from_array = (int ****)malloc((st->radius+1)*sizeof(int ***));
for (k=0; k <= st->radius; k++) {
allocate_lense(st);
st->draw_routine(st, st->orig_map, st->buffer_map, st->xy_coo[k].x, st->xy_coo[k].y, st->fast_from);
-# ifdef HAVE_XSHM_EXTENSION
- if (st->use_shm)
- XShmPutImage(st->dpy, st->window, st->gc, st->buffer_map, 0, 0, st->xy_coo[k].x, st->xy_coo[k].y,
- 2*st->radius+st->speed+2, 2*st->radius+st->speed+2, False);
- else
-
- if (!st->use_shm)
-# endif
- XPutImage(st->dpy, st->window, st->gc, st->buffer_map, 0, 0, st->xy_coo[k].x, st->xy_coo[k].y,
- 2*st->radius+st->speed+2, 2*st->radius+st->speed+2);
-
+ put_xshm_image(st->dpy, st->window, st->gc, st->buffer_map, 0, 0, st->xy_coo[k].x, st->xy_coo[k].y,
+ 2*st->radius+st->speed+2, 2*st->radius+st->speed+2, &st->shm_info);
}
if (!st->img_loader &&
st->start_time + st->duration < time ((time_t *) 0)) {
+ if (st->pm) XFreePixmap (st->dpy, st->pm);
+ st->pm = XCreatePixmap (st->dpy, st->window,
+ st->xgwa.width, st->xgwa.height, st->xgwa.depth);
st->img_loader = load_image_async_simple (0, st->xgwa.screen, st->window,
- st->window, 0, 0);
+ st->pm, 0, 0);
return st->delay;
}
distort_free (Display *dpy, Window window, void *closure)
{
struct state *st = (struct state *) closure;
+ int i, j;
XFreeGC (st->dpy, st->gc);
+ if (st->pm) XFreePixmap (dpy, st->pm);
if (st->orig_map) XDestroyImage (st->orig_map);
- if (st->buffer_map) XDestroyImage (st->buffer_map);
- if (st->from) free (st->from);
+ if (st->buffer_map)
+ destroy_xshm_image (st->dpy, st->buffer_map, &st->shm_info);
if (st->fast_from) free (st->fast_from);
if (st->from_array) free (st->from_array);
+ if (st->buffer_map_cache) free (st->buffer_map_cache);
+
+ if (st->from) {
+ for (i = 0; i < st->from_size; i++)
+ if (st->from[i]) {
+ for (j = 0; j < st->from_size; j++) {
+ if (st->from[i][j]) free (st->from[i][j]);
+ }
+ free (st->from[i]);
+ }
+ free (st->from);
+ }
+
free (st);
}
\f
static const char *distort_defaults [] = {
- "*dontClearRoot: True",
- "*background: Black",
- "*fpsSolid: true",
-#ifdef __sgi /* really, HAVE_READ_DISPLAY_EXTENSION */
- "*visualID: Best",
-#endif
-
+ "*dontClearRoot: True",
+ "*background: Black",
+ "*fpsSolid: true",
"*delay: 20000",
"*duration: 120",
"*radius: 0",
#ifdef HAVE_XSHM_EXTENSION
"*useSHM: False", /* xshm turns out not to help. */
#endif /* HAVE_XSHM_EXTENSION */
-#ifdef USE_IPHONE
+#ifdef HAVE_MOBILE
"*ignoreRotation: True",
"*rotateImages: True",
#endif