diff options
Diffstat (limited to 'hacks/glx/carousel.c')
| -rw-r--r-- | hacks/glx/carousel.c | 958 |
1 files changed, 0 insertions, 958 deletions
diff --git a/hacks/glx/carousel.c b/hacks/glx/carousel.c deleted file mode 100644 index ec207a4..0000000 --- a/hacks/glx/carousel.c +++ /dev/null @@ -1,958 +0,0 @@ -/* carousel, Copyright (c) 2005-2018 Jamie Zawinski <jwz@jwz.org> - * Loads a sequence of images and rotates them around. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation. No representations are made about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * Created: 21-Feb-2005 - */ - -#define DEF_FONT \ - "OCR A Std 48, Lucida Console 48, Monaco 48, Courier 48, monospace 48" -#define DEF_TITLE_FONT "sans-serif bold 48" - -#define DEFAULTS "*count: 7 \n" \ - "*delay: 10000 \n" \ - "*wireframe: False \n" \ - "*showFPS: False \n" \ - "*fpsSolid: True \n" \ - "*useSHM: True \n" \ - "*font: " DEF_FONT "\n" \ - "*titleFont: " DEF_TITLE_FONT "\n" \ - "*desktopGrabber: xscreensaver-getimage -no-desktop %s\n" \ - "*grabDesktopImages: False \n" \ - "*chooseRandomImages: True \n" - -# define release_carousel 0 -# include "xlockmore.h" - -#ifdef USE_GL - -# define DEF_SPEED "1.0" -# define DEF_DURATION "20" -# define DEF_TITLES "True" -# define DEF_ZOOM "True" -# define DEF_TILT "XY" -# define DEF_MIPMAP "True" -# define DEF_DEBUG "False" - -#include "rotator.h" -#include "gltrackball.h" -#include "grab-ximage.h" -#include "texfont.h" - -# ifndef HAVE_JWXYZ -# include <X11/Intrinsic.h> /* for XrmDatabase in -debug mode */ -# endif - -/* Should be in <GL/glext.h> */ -# ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT -# define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE -# endif -# ifndef GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT -# define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF -# endif - -typedef struct { - double x, y, w, h; -} rect; - -typedef enum { EARLY, NORMAL, LOADING, OUT, IN, DEAD } fade_mode; -static int fade_ticks = 60; - -typedef struct { - char *title; /* the filename of this image */ - int w, h; /* size in pixels of the image */ - int tw, th; /* size in pixels of the texture */ - XRectangle geom; /* where in the image the bits are */ - GLuint texid; -} image; - -typedef struct { - ModeInfo *mi; - image current, loading; - GLfloat r, theta; /* radius and rotation on the tube */ - rotator *rot; /* for zoomery */ - Bool from_top_p; /* whether this image drops in or rises up */ - time_t expires; /* when this image should be replaced */ - fade_mode mode; /* in/out animation state */ - int mode_tick; - Bool loaded_p; /* whether background load is done */ -} image_frame; - - -typedef struct { - GLXContext *glx_context; - GLfloat anisotropic; - rotator *rot; - trackball_state *trackball; - Bool button_down_p; - time_t button_down_time; - - int nframes; /* how many frames are loaded */ - int frames_size; - image_frame **frames; /* pointers to the frames */ - - Bool awaiting_first_images_p; - int loads_in_progress; - - texture_font_data *texfont, *titlefont; - - fade_mode mode; - int mode_tick; - - int loading_sw, loading_sh; - - time_t last_time, now; - int draw_tick; - -} carousel_state; - -static carousel_state *sss = NULL; - - -/* Command-line arguments - */ -static GLfloat speed; /* animation speed scale factor */ -static int duration; /* reload images after this long */ -static Bool mipmap_p; /* Use mipmaps instead of single textures. */ -static Bool titles_p; /* Display image titles. */ -static Bool zoom_p; /* Throb the images in and out as they spin. */ -static char *tilt_str; -static Bool tilt_x_p; /* Tilt axis towards the viewer */ -static Bool tilt_y_p; /* Tilt axis side to side */ -static Bool debug_p; /* Be loud and do weird things. */ - - -static XrmOptionDescRec opts[] = { - {"-zoom", ".zoom", XrmoptionNoArg, "True" }, - {"-no-zoom", ".zoom", XrmoptionNoArg, "False" }, - {"-tilt", ".tilt", XrmoptionSepArg, 0 }, - {"-no-tilt", ".tilt", XrmoptionNoArg, "" }, - {"-titles", ".titles", XrmoptionNoArg, "True" }, - {"-no-titles", ".titles", XrmoptionNoArg, "False" }, - {"-mipmaps", ".mipmap", XrmoptionNoArg, "True" }, - {"-no-mipmaps", ".mipmap", XrmoptionNoArg, "False" }, - {"-duration", ".duration", XrmoptionSepArg, 0 }, - {"-debug", ".debug", XrmoptionNoArg, "True" }, - {"-font", ".font", XrmoptionSepArg, 0 }, - {"-speed", ".speed", XrmoptionSepArg, 0 }, -}; - -static argtype vars[] = { - { &mipmap_p, "mipmap", "Mipmap", DEF_MIPMAP, t_Bool}, - { &debug_p, "debug", "Debug", DEF_DEBUG, t_Bool}, - { &titles_p, "titles", "Titles", DEF_TITLES, t_Bool}, - { &zoom_p, "zoom", "Zoom", DEF_ZOOM, t_Bool}, - { &tilt_str, "tilt", "Tilt", DEF_TILT, t_String}, - { &speed, "speed", "Speed", DEF_SPEED, t_Float}, - { &duration, "duration", "Duration", DEF_DURATION, t_Int}, -}; - -ENTRYPOINT ModeSpecOpt carousel_opts = {countof(opts), opts, countof(vars), vars, NULL}; - - -/* Allocates a frame structure and stores it in the list. - */ -static image_frame * -alloc_frame (ModeInfo *mi) -{ - carousel_state *ss = &sss[MI_SCREEN(mi)]; - image_frame *frame = (image_frame *) calloc (1, sizeof (*frame)); - - frame->mi = mi; - frame->mode = EARLY; - frame->rot = make_rotator (0, 0, 0, 0, 0.04 * frand(1.0) * speed, False); - - glGenTextures (1, &frame->current.texid); - glGenTextures (1, &frame->loading.texid); - if (frame->current.texid <= 0) abort(); - if (frame->loading.texid <= 0) abort(); - - if (ss->frames_size <= ss->nframes) - { - ss->frames_size = (ss->frames_size * 1.2) + ss->nframes; - ss->frames = (image_frame **) - realloc (ss->frames, ss->frames_size * sizeof(*ss->frames)); - if (! ss->frames) - { - fprintf (stderr, "%s: out of memory (%d images)\n", - progname, ss->frames_size); - exit (1); - } - } - - ss->frames[ss->nframes++] = frame; - - return frame; -} - - -static void image_loaded_cb (const char *filename, XRectangle *geom, - int image_width, int image_height, - int texture_width, int texture_height, - void *closure); - - -/* Load a new file into the given image struct. - */ -static void -load_image (ModeInfo *mi, image_frame *frame) -{ - carousel_state *ss = &sss[MI_SCREEN(mi)]; - int wire = MI_IS_WIREFRAME(mi); - - if (debug_p && !wire && frame->current.w != 0) - fprintf (stderr, "%s: dropped %4d x %-4d %4d x %-4d \"%s\"\n", - progname, - frame->current.geom.width, - frame->current.geom.height, - frame->current.tw, frame->current.th, - (frame->current.title ? frame->current.title : "(null)")); - - switch (frame->mode) - { - case EARLY: break; - case NORMAL: frame->mode = LOADING; break; - default: abort(); - } - - ss->loads_in_progress++; - - if (wire) - image_loaded_cb (0, 0, 0, 0, 0, 0, frame); - else - { - int w = (MI_WIDTH(mi) / 2) - 1; - int h = (MI_HEIGHT(mi) / 2) - 1; - if (w <= 10) w = 10; - if (h <= 10) h = 10; - - if (w > h * 5) { /* tiny window: use 16:9 boxes */ - h = w * 9/16; - } - - load_texture_async (mi->xgwa.screen, mi->window, *ss->glx_context, w, h, - mipmap_p, frame->loading.texid, - image_loaded_cb, frame); - } -} - - -/* Callback that tells us that the texture has been loaded. - */ -static void -image_loaded_cb (const char *filename, XRectangle *geom, - int image_width, int image_height, - int texture_width, int texture_height, - void *closure) -{ - image_frame *frame = (image_frame *) closure; - ModeInfo *mi = frame->mi; - carousel_state *ss = &sss[MI_SCREEN(mi)]; - int wire = MI_IS_WIREFRAME(mi); - - if (wire) - { - frame->loading.w = MI_WIDTH (mi) * (0.5 + frand (1.0)); - frame->loading.h = MI_HEIGHT (mi); - frame->loading.geom.width = frame->loading.w; - frame->loading.geom.height = frame->loading.h; - goto DONE; - } - - if (image_width == 0 || image_height == 0) - exit (1); - - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, - mipmap_p ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR); - - if (ss->anisotropic >= 1.0) - glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, - ss->anisotropic); - - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - - frame->loading.w = image_width; - frame->loading.h = image_height; - frame->loading.tw = texture_width; - frame->loading.th = texture_height; - frame->loading.geom = *geom; - - if (frame->loading.title) - free (frame->loading.title); - frame->loading.title = (filename ? strdup (filename) : 0); - - /* xscreensaver-getimage returns paths relative to the image directory - now, so leave the sub-directory part in. Unless it's an absolute path. - */ - if (frame->loading.title && frame->loading.title[0] == '/') - { /* strip filename to part after last /. */ - char *s = strrchr (frame->loading.title, '/'); - if (s) strcpy (frame->loading.title, s+1); - } - - if (debug_p) - fprintf (stderr, "%s: loaded %4d x %-4d %4d x %-4d \"%s\"\n", - progname, - frame->loading.geom.width, - frame->loading.geom.height, - frame->loading.tw, frame->loading.th, - (frame->loading.title ? frame->loading.title : "(null)")); - - DONE: - - frame->loaded_p = True; - - if (ss->loads_in_progress <= 0) abort(); - ss->loads_in_progress--; - - /* This image expires N seconds after it finished loading. */ - frame->expires = time((time_t *) 0) + (duration * MI_COUNT(mi)); - - switch (frame->mode) - { - case EARLY: /* part of the initial batch of images */ - { - image swap = frame->current; - frame->current = frame->loading; - frame->loading = swap; - } - break; - case LOADING: /* start dropping the old image out */ - { - frame->mode = OUT; - frame->mode_tick = fade_ticks / speed; - frame->from_top_p = random() & 1; - } - break; - default: - abort(); - } -} - - -static void loading_msg (ModeInfo *mi, int n); - -static Bool -load_initial_images (ModeInfo *mi) -{ - carousel_state *ss = &sss[MI_SCREEN(mi)]; - int i; - Bool all_loaded_p = True; - for (i = 0; i < ss->nframes; i++) - if (! ss->frames[i]->loaded_p) - all_loaded_p = False; - - if (all_loaded_p) - { - if (ss->nframes < MI_COUNT (mi)) - { - /* The frames currently on the list are fully loaded. - Start the next one loading. (We run the image loader - asynchronously, but we load them one at a time.) - */ - load_image (mi, alloc_frame (mi)); - } - else - { - /* The first batch of images are now all loaded! - Stagger the expire times so that they don't all drop out at once. - */ - time_t now = time((time_t *) 0); - int i; - - for (i = 0; i < ss->nframes; i++) - { - image_frame *frame = ss->frames[i]; - frame->r = 1.0; - frame->theta = i * 360.0 / ss->nframes; - frame->expires = now + (duration * (i + 1)); - frame->mode = NORMAL; - } - - /* Instead of always going clockwise, shuffle the expire times - of the frames so that they drop out in a random order. - */ - for (i = 0; i < ss->nframes; i++) - { - image_frame *frame1 = ss->frames[i]; - image_frame *frame2 = ss->frames[random() % ss->nframes]; - time_t swap = frame1->expires; - frame1->expires = frame2->expires; - frame2->expires = swap; - } - - ss->awaiting_first_images_p = False; - } - } - - loading_msg (mi, ss->nframes-1); - - return !ss->awaiting_first_images_p; -} - - -ENTRYPOINT void -reshape_carousel (ModeInfo *mi, int width, int height) -{ - GLfloat h = (GLfloat) height / (GLfloat) width; - int y = 0; - - if (width > height * 5) { /* tiny window: show middle */ - height = width * 9/16; - y = -height/2; - h = height / (GLfloat) width; - } - - glViewport (0, y, (GLint) width, (GLint) height); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluPerspective (60.0, 1/h, 1.0, 8.0); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - gluLookAt( 0.0, 0.0, 2.6, - 0.0, 0.0, 0.0, - 0.0, 1.0, 0.0); - - glClear(GL_COLOR_BUFFER_BIT); -} - - -ENTRYPOINT Bool -carousel_handle_event (ModeInfo *mi, XEvent *event) -{ - carousel_state *ss = &sss[MI_SCREEN(mi)]; - - if (event->xany.type == ButtonPress && - event->xbutton.button == Button1) - { - if (! ss->button_down_p) - ss->button_down_time = time((time_t *) 0); - } - else if (event->xany.type == ButtonRelease && - event->xbutton.button == Button1) - { - if (ss->button_down_p) - { - /* Add the time the mouse was held to the expire times of all - frames, so that mouse-dragging doesn't count against - image expiration. - */ - int secs = time((time_t *) 0) - ss->button_down_time; - int i; - for (i = 0; i < ss->nframes; i++) - ss->frames[i]->expires += secs; - } - } - - if (gltrackball_event_handler (event, ss->trackball, - MI_WIDTH (mi), MI_HEIGHT (mi), - &ss->button_down_p)) - return True; - else if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event)) - { - int i = random() % ss->nframes; - ss->frames[i]->expires = 0; - return True; - } - - return False; -} - - -/* Kludge to add "-v" to invocation of "xscreensaver-getimage" in -debug mode - */ -static void -hack_resources (Display *dpy) -{ -# ifndef HAVE_JWXYZ - char *res = "desktopGrabber"; - char *val = get_string_resource (dpy, res, "DesktopGrabber"); - char buf1[255]; - char buf2[255]; - XrmValue value; - XrmDatabase db = XtDatabase (dpy); - sprintf (buf1, "%.100s.%.100s", progname, res); - sprintf (buf2, "%.200s -v", val); - value.addr = buf2; - value.size = strlen(buf2); - XrmPutResource (&db, buf1, "String", &value); - free (val); -# endif /* !HAVE_JWXYZ */ -} - - -static void -loading_msg (ModeInfo *mi, int n) -{ - carousel_state *ss = &sss[MI_SCREEN(mi)]; - int wire = MI_IS_WIREFRAME(mi); - char text[100]; - - if (wire) return; - - if (n == 0) - sprintf (text, "Loading images..."); - else - sprintf (text, "Loading images... (%d%%)", - (int) (n * 100 / MI_COUNT(mi))); - - if (ss->loading_sw == 0) - { - /* only do this once, so that the string doesn't move. */ - XCharStruct e; - texture_string_metrics (ss->titlefont, text, &e, 0, 0); - ss->loading_sw = e.width; - ss->loading_sh = e.ascent + e.descent; - } - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - -/* - { - double rot = current_device_rotation(); - 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); - } - } -*/ - - { - GLfloat s = (MI_WIDTH(mi) < MI_HEIGHT(mi) - ? (MI_WIDTH(mi) / (GLfloat) MI_HEIGHT(mi)) - : 1); - glRotatef (current_device_rotation(), 0, 0, 1); - glScalef (s, s, s); - } - - glOrtho(0, MI_WIDTH(mi), 0, MI_HEIGHT(mi), -1, 1); - glTranslatef ((MI_WIDTH(mi) - ss->loading_sw) / 2, - (MI_HEIGHT(mi) - ss->loading_sh) / 2, - 0); - glColor3f (1, 1, 0); - glEnable (GL_TEXTURE_2D); - glDisable (GL_DEPTH_TEST); -# ifndef HAVE_ANDROID /* Doesn't work -- photo displays as static */ - print_texture_string (ss->titlefont, text); -# endif - glEnable (GL_DEPTH_TEST); - glPopMatrix(); - - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - - glMatrixMode(GL_MODELVIEW); - - glFinish(); - glXSwapBuffers (MI_DISPLAY (mi), MI_WINDOW(mi)); -} - - -ENTRYPOINT void -init_carousel (ModeInfo *mi) -{ - int screen = MI_SCREEN(mi); - carousel_state *ss; - int wire = MI_IS_WIREFRAME(mi); - - MI_INIT (mi, sss); - ss = &sss[screen]; - - if ((ss->glx_context = init_GL(mi)) != NULL) { - reshape_carousel (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); - clear_gl_error(); /* WTF? sometimes "invalid op" from glViewport! */ - } else { - MI_CLEARWINDOW(mi); - } - - if (!tilt_str || !*tilt_str) - ; - else if (!strcasecmp (tilt_str, "0")) - ; - else if (!strcasecmp (tilt_str, "X")) - tilt_x_p = 1; - else if (!strcasecmp (tilt_str, "Y")) - tilt_y_p = 1; - else if (!strcasecmp (tilt_str, "XY")) - tilt_x_p = tilt_y_p = 1; - else - { - fprintf (stderr, "%s: tilt must be 'X', 'Y', 'XY' or '', not '%s'\n", - progname, tilt_str); - exit (1); - } - - { - double spin_speed = speed * 0.2; /* rotation of tube around axis */ - double spin_accel = speed * 0.1; - double wander_speed = speed * 0.001; /* tilting of axis */ - - spin_speed *= 0.9 + frand(0.2); - wander_speed *= 0.9 + frand(0.2); - - ss->rot = make_rotator (spin_speed, spin_speed, spin_speed, - spin_accel, wander_speed, True); - - ss->trackball = gltrackball_init (False); - } - - if (strstr ((char *) glGetString(GL_EXTENSIONS), - "GL_EXT_texture_filter_anisotropic")) - glGetFloatv (GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &ss->anisotropic); - else - ss->anisotropic = 0.0; - - glDisable (GL_LIGHTING); - glEnable (GL_DEPTH_TEST); - glDisable (GL_CULL_FACE); - - if (! wire) - { - glShadeModel (GL_SMOOTH); - glEnable (GL_LINE_SMOOTH); - /* This gives us a transparent diagonal slice through each image! */ - /* glEnable (GL_POLYGON_SMOOTH); */ - glHint (GL_LINE_SMOOTH_HINT, GL_NICEST); - glEnable (GL_BLEND); - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable (GL_ALPHA_TEST); - - glEnable (GL_POLYGON_OFFSET_FILL); - glPolygonOffset (1.0, 1.0); - - } - - ss->texfont = load_texture_font (MI_DISPLAY(mi), "font"); - ss->titlefont = load_texture_font (MI_DISPLAY(mi), "titleFont"); - - if (debug_p) - hack_resources (MI_DISPLAY (mi)); - - ss->nframes = 0; - ss->frames_size = 10; - ss->frames = (image_frame **) - calloc (1, ss->frames_size * sizeof(*ss->frames)); - - ss->mode = IN; - ss->mode_tick = fade_ticks / speed; - - ss->awaiting_first_images_p = True; -} - - -static void -draw_frame (ModeInfo *mi, image_frame *frame, time_t now, Bool body_p) -{ - carousel_state *ss = &sss[MI_SCREEN(mi)]; - int wire = MI_IS_WIREFRAME(mi); - - GLfloat texw = frame->current.geom.width / (GLfloat) frame->current.tw; - GLfloat texh = frame->current.geom.height / (GLfloat) frame->current.th; - GLfloat texx1 = frame->current.geom.x / (GLfloat) frame->current.tw; - GLfloat texy1 = frame->current.geom.y / (GLfloat) frame->current.th; - GLfloat texx2 = texx1 + texw; - GLfloat texy2 = texy1 + texh; - GLfloat aspect = ((GLfloat) frame->current.geom.height / - (GLfloat) frame->current.geom.width); - - glBindTexture (GL_TEXTURE_2D, frame->current.texid); - - glPushMatrix(); - - /* Position this image on the wheel. - */ - glRotatef (frame->theta, 0, 1, 0); - glTranslatef (0, 0, frame->r); - - /* Scale down the image so that all N frames fit on the wheel - without bumping in to each other. - */ - { - GLfloat t, s; - switch (ss->nframes) - { - case 1: t = -1.0; s = 1.7; break; - case 2: t = -0.8; s = 1.6; break; - case 3: t = -0.4; s = 1.5; break; - case 4: t = -0.2; s = 1.3; break; - default: t = 0.0; s = 6.0 / ss->nframes; break; - } - glTranslatef (0, 0, t); - glScalef (s, s, s); - } - - /* Center this image on the wheel plane. - */ - glTranslatef (-0.5, -(aspect/2), 0); - - /* Move as per the "zoom in and out" setting. - */ - if (zoom_p) - { - double x, y, z; - /* Only use the Z component of the rotator for in/out position. */ - get_position (frame->rot, &x, &y, &z, !ss->button_down_p); - glTranslatef (0, 0, z/2); - } - - /* Compute the "drop in and out" state. - */ - switch (frame->mode) - { - case EARLY: - abort(); - break; - case NORMAL: - if (!ss->button_down_p && - now >= frame->expires && - ss->loads_in_progress == 0) /* only load one at a time */ - load_image (mi, frame); - break; - case LOADING: - break; - case OUT: - if (--frame->mode_tick <= 0) { - image swap = frame->current; - frame->current = frame->loading; - frame->loading = swap; - - frame->mode = IN; - frame->mode_tick = fade_ticks / speed; - } - break; - case IN: - if (--frame->mode_tick <= 0) - frame->mode = NORMAL; - break; - default: - abort(); - } - - /* Now translate for current in/out state. - */ - if (frame->mode == OUT || frame->mode == IN) - { - GLfloat t = (frame->mode == OUT - ? frame->mode_tick / (fade_ticks / speed) - : (((fade_ticks / speed) - frame->mode_tick + 1) / - (fade_ticks / speed))); - t = 5 * (1 - t); - if (frame->from_top_p) t = -t; - glTranslatef (0, t, 0); - } - - if (body_p) /* Draw the image quad. */ - { - if (! wire) - { - glColor3f (1, 1, 1); - glNormal3f (0, 0, 1); - glEnable (GL_TEXTURE_2D); - glBegin (GL_QUADS); - glNormal3f (0, 0, 1); - glTexCoord2f (texx1, texy2); glVertex3f (0, 0, 0); - glTexCoord2f (texx2, texy2); glVertex3f (1, 0, 0); - glTexCoord2f (texx2, texy1); glVertex3f (1, aspect, 0); - glTexCoord2f (texx1, texy1); glVertex3f (0, aspect, 0); - glEnd(); - } - - /* Draw a box around it. - */ - glLineWidth (2.0); - glColor3f (0.5, 0.5, 0.5); - glDisable (GL_TEXTURE_2D); - glBegin (GL_LINE_LOOP); - glVertex3f (0, 0, 0); - glVertex3f (1, 0, 0); - glVertex3f (1, aspect, 0); - glVertex3f (0, aspect, 0); - glEnd(); - - } - else if (frame->current.title && *frame->current.title) - { /* Draw a title under the image. */ - XCharStruct e; - int sw, sh; - GLfloat scale = 0.05; - char *title = frame->current.title ? frame->current.title : "(untitled)"; - texture_string_metrics (ss->texfont, title, &e, 0, 0); - sw = e.width; - sh = e.ascent + e.descent; - - glTranslatef (0, -scale, 0); - - scale /= sh; - glScalef (scale, scale, scale); - - glTranslatef (((1/scale) - sw) / 2, 0, 0); - glColor3f (1, 1, 1); - - if (!wire) - { - glEnable (GL_TEXTURE_2D); -# ifndef HAVE_ANDROID /* Doesn't work -- photo displays as static */ - print_texture_string (ss->texfont, title); -# endif - } - else - { - glBegin (GL_LINE_LOOP); - glVertex3f (0, 0, 0); - glVertex3f (sw, 0, 0); - glVertex3f (sw, sh, 0); - glVertex3f (0, sh, 0); - glEnd(); - } - } - - glPopMatrix(); -} - - -ENTRYPOINT void -draw_carousel (ModeInfo *mi) -{ - carousel_state *ss = &sss[MI_SCREEN(mi)]; - int i; - - if (!ss->glx_context) - return; - - glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *ss->glx_context); - - if (ss->awaiting_first_images_p) - if (!load_initial_images (mi)) - return; - - /* Only check the wall clock every 10 frames */ - { - if (ss->now == 0 || ss->draw_tick++ > 10) - { - ss->now = time((time_t *) 0); - if (ss->last_time == 0) ss->last_time = ss->now; - ss->draw_tick = 0; - } - } - - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glPushMatrix(); - - glRotatef(current_device_rotation(), 0, 0, 1); - - - /* Run the startup "un-shrink" animation. - */ - switch (ss->mode) - { - case IN: - if (--ss->mode_tick <= 0) - { - ss->mode = NORMAL; - ss->last_time = time((time_t *) 0); - } - break; - case NORMAL: - break; - default: - abort(); - } - - - /* Scale as per the startup "un-shrink" animation. - */ - if (ss->mode != NORMAL) - { - GLfloat s = (ss->mode == OUT - ? ss->mode_tick / (fade_ticks / speed) - : (((fade_ticks / speed) - ss->mode_tick + 1) / - (fade_ticks / speed))); - glScalef (s, s, s); - } - - /* Rotate and tilt as per the user, and the motion modeller. - */ - { - double x, y, z; - gltrackball_rotate (ss->trackball); - - /* Tilt the tube up or down by up to 30 degrees */ - get_position (ss->rot, &x, &y, &z, !ss->button_down_p); - if (tilt_x_p) - glRotatef (15 - (x * 30), 1, 0, 0); - if (tilt_y_p) - glRotatef (7 - (y * 14), 0, 0, 1); - - /* Only use the Y component of the rotator. */ - get_rotation (ss->rot, &x, &y, &z, !ss->button_down_p); - glRotatef (y * 360, 0, 1, 0); - } - - /* First draw each image, then draw the titles. GL insists that you - draw back-to-front in order to make alpha blending work properly, - so we need to draw all of the 100% opaque images before drawing - any of the not-100%-opaque titles. - */ - for (i = 0; i < ss->nframes; i++) - draw_frame (mi, ss->frames[i], ss->now, True); - if (titles_p) - for (i = 0; i < ss->nframes; i++) - draw_frame (mi, ss->frames[i], ss->now, False); - - glPopMatrix(); - - if (mi->fps_p) do_fps (mi); - glFinish(); - glXSwapBuffers (MI_DISPLAY (mi), MI_WINDOW(mi)); -} - - -ENTRYPOINT void -free_carousel (ModeInfo *mi) -{ - carousel_state *ss = &sss[MI_SCREEN(mi)]; - int i; - if (!ss->glx_context) return; - glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *ss->glx_context); - if (ss->rot) free_rotator (ss->rot); - if (ss->trackball) gltrackball_free (ss->trackball); - if (ss->texfont) free_texture_font (ss->texfont); - if (ss->titlefont) free_texture_font (ss->titlefont); - for (i = 0; i < ss->nframes; i++) { - if (ss->frames[i]->current.title) free (ss->frames[i]->current.title); - if (ss->frames[i]->loading.title) free (ss->frames[i]->loading.title); - if (ss->frames[i]->rot) free_rotator (ss->frames[i]->rot); - if (ss->frames[i]->current.texid) - glDeleteTextures (1, &ss->frames[i]->current.texid); - if (ss->frames[i]->loading.texid) - glDeleteTextures (1, &ss->frames[i]->loading.texid); - } -} - -XSCREENSAVER_MODULE ("Carousel", carousel) - -#endif /* USE_GL */ |
