X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fglx%2Fglslideshow.c;h=3e3548d8e08f6df20ded6b18d5c73c3b81fd11ab;hb=aa75c7476aeaa84cf3abc192b376a8b03c325213;hp=162d4ff87a84bfb0c53a5caf9540b196e94b0f25;hpb=447db08c956099b3b183886729108bf5b364c4b8;p=xscreensaver diff --git a/hacks/glx/glslideshow.c b/hacks/glx/glslideshow.c index 162d4ff8..3e3548d8 100644 --- a/hacks/glx/glslideshow.c +++ b/hacks/glx/glslideshow.c @@ -1,4 +1,4 @@ -/* glslideshow, Copyright (c) 2003-2005 Jamie Zawinski +/* glslideshow, Copyright (c) 2003-2014 Jamie Zawinski * Loads a sequence of images and smoothly pans around them; crossfades * when loading new images. * @@ -68,34 +68,18 @@ * thread support at a lower level? */ -#include - -# define PROGCLASS "GLSlideshow" -# define HACK_INIT init_slideshow -# define HACK_DRAW draw_slideshow -# define HACK_RESHAPE reshape_slideshow -# define HACK_HANDLE_EVENT glslideshow_handle_event -# define EVENT_MASK (ExposureMask|VisibilityChangeMask) -# define slideshow_opts xlockmore_opts - -# define DEF_FADE_DURATION "2" -# define DEF_PAN_DURATION "6" -# define DEF_IMAGE_DURATION "30" -# define DEF_ZOOM "75" -# define DEF_FPS_CUTOFF "5" -# define DEF_TITLES "False" -# define DEF_LETTERBOX "True" -# define DEF_DEBUG "False" -# define DEF_MIPMAP "True" - #define DEFAULTS "*delay: 20000 \n" \ "*wireframe: False \n" \ "*showFPS: False \n" \ "*fpsSolid: True \n" \ "*useSHM: True \n" \ - "*titleFont: -*-times-bold-r-normal-*-180-*\n" \ - "*desktopGrabber: xscreensaver-getimage -no-desktop %s\n" + "*titleFont: -*-helvetica-medium-r-normal-*-*-180-*-*-*-*-*-*\n" \ + "*desktopGrabber: xscreensaver-getimage -no-desktop %s\n" \ + "*grabDesktopImages: False \n" \ + "*chooseRandomImages: True \n" +# define refresh_slideshow 0 +# define release_slideshow 0 # include "xlockmore.h" #undef countof @@ -103,15 +87,19 @@ #ifdef USE_GL -#include -#include -#include -#include -#include -#include "grab-ximage.h" -#include "glxfonts.h" -extern XtAppContext app; +# define DEF_FADE_DURATION "2" +# define DEF_PAN_DURATION "6" +# define DEF_IMAGE_DURATION "30" +# define DEF_ZOOM "75" +# define DEF_FPS_CUTOFF "5" +# define DEF_TITLES "False" +# define DEF_LETTERBOX "True" +# define DEF_DEBUG "False" +# define DEF_MIPMAP "True" + +#include "grab-ximage.h" +#include "texfont.h" typedef struct { double x, y, w, h; @@ -160,6 +148,7 @@ typedef struct { double image_load_time; /* time when we last loaded a new image */ double prev_frame_time; /* time when we last drew a frame */ + Bool awaiting_first_image_p; /* Early in startup: nothing to display yet */ Bool redisplay_needed_p; /* Sometimes we can get away with not re-painting. Tick this if a redisplay is required. */ @@ -171,11 +160,13 @@ typedef struct { Bool checked_fps_p; /* Whether we have checked for a low frame rate. */ - XFontStruct *xfont; /* for printing image file names */ - GLuint font_dlist; + texture_font_data *font_data; /* for printing image file names */ int sprite_id, image_id; /* debugging id counters */ + double time_elapsed; + int frames_elapsed; + } slideshow_state; static slideshow_state *sss = NULL; @@ -210,7 +201,8 @@ static XrmOptionDescRec opts[] = { {"-cutoff", ".FPScutoff", XrmoptionSepArg, 0 }, {"-titles", ".titles", XrmoptionNoArg, "True" }, {"-letterbox", ".letterbox", XrmoptionNoArg, "True" }, - {"-clip", ".letterbox", XrmoptionNoArg, "False" }, + {"-no-letterbox", ".letterbox", XrmoptionNoArg, "False" }, + {"-clip", ".letterbox", XrmoptionNoArg, "False" }, {"-mipmaps", ".mipmap", XrmoptionNoArg, "True" }, {"-no-mipmaps", ".mipmap", XrmoptionNoArg, "False" }, {"-debug", ".debug", XrmoptionNoArg, "True" }, @@ -228,12 +220,15 @@ static argtype vars[] = { { &do_titles, "titles", "Titles", DEF_TITLES, t_Bool}, }; -ModeSpecOpt slideshow_opts = {countof(opts), opts, countof(vars), vars, NULL}; +ENTRYPOINT ModeSpecOpt slideshow_opts = {countof(opts), opts, countof(vars), vars, NULL}; static const char * blurb (void) { +# ifdef HAVE_JWXYZ + return "GLSlideshow"; +# else static char buf[255]; time_t now = time ((time_t *) 0); char *ct = (char *) ctime (&now); @@ -245,6 +240,7 @@ blurb (void) strncpy(buf+n, ct+11, 8); strcpy(buf+n+9, ": "); return buf; +# endif } @@ -279,7 +275,6 @@ alloc_image (ModeInfo *mi) slideshow_state *ss = &sss[MI_SCREEN(mi)]; int wire = MI_IS_WIREFRAME(mi); image *img = (image *) calloc (1, sizeof (*img)); - Bool async_p = True; img->id = ++ss->image_id; img->loaded_p = False; @@ -293,22 +288,9 @@ alloc_image (ModeInfo *mi) if (wire) image_loaded_cb (0, 0, 0, 0, 0, 0, img); - else if (async_p) - screen_to_texture_async (mi->xgwa.screen, mi->window, 0, 0, mipmap_p, - img->texid, image_loaded_cb, img); else - { - char *filename = 0; - XRectangle geom; - int iw=0, ih=0, tw=0, th=0; - glBindTexture (GL_TEXTURE_2D, img->texid); - - if (! screen_to_texture (mi->xgwa.screen, mi->window, 0, 0, mipmap_p, - &filename, &geom, &iw, &ih, &tw, &th)) - exit(1); - image_loaded_cb (filename, &geom, iw, ih, tw, th, img); - if (filename) free (filename); - } + load_texture_async (mi->xgwa.screen, mi->window, *ss->glx_context, + 0, 0, mipmap_p, img->texid, image_loaded_cb, img); ss->images[ss->nimages++] = img; if (ss->nimages >= countof(ss->images)) abort(); @@ -317,33 +299,6 @@ alloc_image (ModeInfo *mi) } -/* Block until the first image is completely loaded. - We normally load images in the background, but we have nothing to draw - until we get that first image... - */ -static void -await_first_image (ModeInfo *mi) -{ - slideshow_state *ss = &sss[MI_SCREEN(mi)]; - image *img; - int i = 0; - if (ss->nimages != 0) abort(); - img = alloc_image (mi); - - while (! img->loaded_p) - { - usleep (100000); /* check every 1/10th sec */ - if (i++ > 600) abort(); /* if a minute has passed, we're broken */ - - while (XtAppPending (app) & (XtIMTimer|XtIMAlternateInput)) - XtAppProcessEvent (app, XtIMTimer|XtIMAlternateInput); - } - - if (debug_p) - fprintf (stderr, "\n"); -} - - /* Callback that tells us that the texture has been loaded. */ static void @@ -402,10 +357,16 @@ image_loaded_cb (const char *filename, XRectangle *geom, img->geom.height *= scale; } - if (img->title) /* strip filename to part after last /. */ + /* xscreensaver-getimage returns paths relative to the image directory + now, so leave the sub-directory part in. Unless it's an absolute path. + */ + if (img->title && img->title[0] == '/') { + /* strip filename to part between last "/" and last ".". */ char *s = strrchr (img->title, '/'); if (s) strcpy (img->title, s+1); + s = strrchr (img->title, '.'); + if (s) *s = 0; } if (debug_p) @@ -512,30 +473,22 @@ randomize_sprite (ModeInfo *mi, sprite *sp) int vp_h = MI_HEIGHT(mi); int img_w = sp->img->geom.width; int img_h = sp->img->geom.height; - int min_w, min_h, max_w, max_h; + int min_w, max_w; double ratio = (double) img_h / img_w; if (letterbox_p) { min_w = img_w; - min_h = img_h; } else { if (img_w < vp_w) - { - min_w = vp_w; - min_h = img_h * (float) vp_w / img_w; - } + min_w = vp_w; else - { - min_w = img_w * (float) vp_h / img_h; - min_h = vp_h; - } + min_w = img_w * (float) vp_h / img_h; } max_w = min_w * 100 / zoom; - max_h = min_h * 100 / zoom; sp->from.w = min_w + frand ((max_w - min_w) * 0.4); sp->to.w = max_w - frand ((max_w - min_w) * 0.4); @@ -575,11 +528,22 @@ randomize_sprite (ModeInfo *mi, sprite *sp) sp->from = swap; } - /* Make sure the aspect ratios are within 0.0001 of each other. + /* Make sure the aspect ratios are within 0.001 of each other. */ - if ((int) (0.5 + (sp->from.w * 1000 / sp->from.h)) != - (int) (0.5 + (sp->to.w * 1000 / sp->to.h))) - abort(); + { + int r1 = 0.5 + (sp->from.w * 1000 / sp->from.h); + int r2 = 0.5 + (sp->to.w * 1000 / sp->to.h); + if (r1 < r2-1 || r1 > r2+1) + { + fprintf (stderr, + "%s: botched aspect: %f x %f (%d) vs %f x %f (%d): %s\n", + progname, + sp->from.w, sp->from.h, r1, + sp->to.w, sp->to.h, r2, + (sp->img->title ? sp->img->title : "[null]")); + abort(); + } + } sp->from.x /= vp_w; sp->from.y /= vp_h; @@ -842,19 +806,13 @@ draw_sprite (ModeInfo *mi, sprite *sp) if (do_titles && - img->title && *img->title) + img->title && *img->title && + (sp->state == IN || sp->state == FULL)) { - int x = 10; - int y = mi->xgwa.height - 10; - glColor4f (0, 0, 0, sp->opacity); /* cheap-assed dropshadow */ - print_gl_string (mi->dpy, ss->xfont, ss->font_dlist, - mi->xgwa.width, mi->xgwa.height, x, y, - img->title); - x++; y++; glColor4f (1, 1, 1, sp->opacity); - print_gl_string (mi->dpy, ss->xfont, ss->font_dlist, - mi->xgwa.width, mi->xgwa.height, x, y, - img->title); + print_texture_label (mi->dpy, ss->font_data, + mi->xgwa.width, mi->xgwa.height, + 1, img->title); } } glPopMatrix(); @@ -908,6 +866,22 @@ draw_sprites (ModeInfo *mi) glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); + +/* + { + GLfloat rot = current_device_rotation(); + glTranslatef (0.5, 0.5, 0); + glRotatef(rot, 0, 0, 1); + if ((rot > 45 && rot < 135) || + (rot < -45 && rot > -135)) + { + GLfloat s = MI_WIDTH(mi) / (GLfloat) MI_HEIGHT(mi); + glScalef (s, 1/s, 1); + } + glTranslatef (-0.5, -0.5, 0); + } +*/ + for (i = 0; i < ss->nsprites; i++) draw_sprite (mi, ss->sprites[i]); glPopMatrix(); @@ -931,7 +905,7 @@ draw_sprites (ModeInfo *mi) } -void +ENTRYPOINT void reshape_slideshow (ModeInfo *mi, int width, int height) { slideshow_state *ss = &sss[MI_SCREEN(mi)]; @@ -939,6 +913,7 @@ reshape_slideshow (ModeInfo *mi, int width, int height) glViewport (0, 0, width, height); glMatrixMode (GL_PROJECTION); glLoadIdentity(); + glRotatef (current_device_rotation(), 0, 0, 1); glMatrixMode (GL_MODELVIEW); glLoadIdentity(); @@ -959,29 +934,12 @@ reshape_slideshow (ModeInfo *mi, int width, int height) } -Bool -glslideshow_handle_event (ModeInfo *mi, XEvent *event) +ENTRYPOINT Bool +slideshow_handle_event (ModeInfo *mi, XEvent *event) { slideshow_state *ss = &sss[MI_SCREEN(mi)]; - if (event->xany.type == ButtonPress && - event->xbutton.button == Button1) - { - ss->change_now_p = True; - return True; - } - else if (event->xany.type == KeyPress) - { - KeySym keysym; - char c = 0; - XLookupString (&event->xkey, &c, 1, &keysym, 0); - if (c == ' ' || c == '\r' || c == '\n' || c == '\t') - { - ss->change_now_p = True; - return True; - } - } - else if (event->xany.type == Expose || + if (event->xany.type == Expose || event->xany.type == GraphicsExpose || event->xany.type == VisibilityNotify) { @@ -990,6 +948,11 @@ glslideshow_handle_event (ModeInfo *mi, XEvent *event) fprintf (stderr, "%s: exposure\n", blurb()); return False; } + else if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event)) + { + ss->change_now_p = True; + return True; + } return False; } @@ -1033,21 +996,21 @@ sanity_check (ModeInfo *mi) static void check_fps (ModeInfo *mi) { +#ifndef HAVE_JWXYZ /* always assume Cocoa and mobile are fast enough */ + slideshow_state *ss = &sss[MI_SCREEN(mi)]; - static double time_elapsed = 0; - static int frames_elapsed = 0; double start_time, end_time, wall_elapsed, frame_duration, fps; int i; start_time = ss->now; end_time = double_time(); frame_duration = end_time - start_time; /* time spent drawing this frame */ - time_elapsed += frame_duration; /* time spent drawing all frames */ - frames_elapsed++; + ss->time_elapsed += frame_duration; /* time spent drawing all frames */ + ss->frames_elapsed++; wall_elapsed = end_time - ss->dawn_of_time; - fps = frames_elapsed / time_elapsed; + fps = ss->frames_elapsed / ss->time_elapsed; ss->theoretical_fps = fps; if (ss->checked_fps_p) return; @@ -1062,7 +1025,7 @@ check_fps (ModeInfo *mi) if (debug_p) fprintf (stderr, "%s: %.1f fps is fast enough (with %d frames in %.1f secs)\n", - blurb(), fps, frames_elapsed, wall_elapsed); + blurb(), fps, ss->frames_elapsed, wall_elapsed); return; } @@ -1085,6 +1048,7 @@ check_fps (ModeInfo *mi) /* Need this in case zoom changed. */ reshape_slideshow (mi, mi->xgwa.width, mi->xgwa.height); +#endif /* HAVE_JWXYZ */ } @@ -1108,7 +1072,7 @@ hack_resources (void) } -void +ENTRYPOINT void init_slideshow (ModeInfo *mi) { int screen = MI_SCREEN(mi); @@ -1154,7 +1118,7 @@ init_slideshow (ModeInfo *mi) if (debug_p) glLineWidth (3); - load_font (mi->dpy, "titleFont", &ss->xfont, &ss->font_dlist); + ss->font_data = load_texture_font (mi->dpy, "titleFont"); if (debug_p) hack_resources(); @@ -1163,16 +1127,12 @@ init_slideshow (ModeInfo *mi) ss->dawn_of_time = ss->now; ss->prev_frame_time = ss->now; - await_first_image (mi); /* wait for first image to fully load */ - - ss->now = double_time(); - ss->dawn_of_time = ss->now; - - new_sprite (mi); /* start first sprite fading in */ + ss->awaiting_first_image_p = True; + alloc_image (mi); } -void +ENTRYPOINT void draw_slideshow (ModeInfo *mi) { slideshow_state *ss = &sss[MI_SCREEN(mi)]; @@ -1181,6 +1141,22 @@ draw_slideshow (ModeInfo *mi) if (!ss->glx_context) return; + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(ss->glx_context)); + + if (ss->awaiting_first_image_p) + { + image *img = ss->images[0]; + if (!img) abort(); + if (!img->loaded_p) + return; + + ss->awaiting_first_image_p = False; + ss->dawn_of_time = double_time(); + + /* start the very first sprite fading in */ + new_sprite (mi); + } + ss->now = double_time(); /* Each sprite has three states: fading in, full, fading out. @@ -1236,8 +1212,7 @@ draw_slideshow (ModeInfo *mi) draw_sprites (mi); - ss->fps = fps_1 (mi); - if (mi->fps_p) fps_2 (mi); + if (mi->fps_p) do_fps (mi); glFinish(); glXSwapBuffers (MI_DISPLAY (mi), MI_WINDOW(mi)); @@ -1246,4 +1221,6 @@ draw_slideshow (ModeInfo *mi) check_fps (mi); } +XSCREENSAVER_MODULE_2 ("GLSlideshow", glslideshow, slideshow) + #endif /* USE_GL */