X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=utils%2Ffade.c;h=18e940680a1fb8d607118d66ac68e57058a12f23;hb=bbd0773f2adde4927a6196361d4061e70bf48cd9;hp=1b975f681ca403d93354b983e6dce635d3a1dff8;hpb=585e1a6717d1dd9b90fbb53acaaae82106354d33;p=xscreensaver diff --git a/utils/fade.c b/utils/fade.c index 1b975f68..18e94068 100644 --- a/utils/fade.c +++ b/utils/fade.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 1992-2001 Jamie Zawinski +/* xscreensaver, Copyright (c) 1992-2003 Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -73,24 +73,28 @@ blacken_colormap (Screen *screen, Colormap cmap) static void fade_screens_1 (Display *dpy, Colormap *cmaps, - Window *black_windows, int seconds, int ticks, + Window *black_windows, int nwindows, + int seconds, int ticks, Bool out_p, Bool clear_windows); #ifdef HAVE_SGI_VC_EXTENSION static int sgi_gamma_fade (Display *dpy, - Window *black_windows, int seconds, int ticks, + Window *black_windows, int nwindows, + int seconds, int ticks, Bool out_p, Bool clear_windows); #endif /* HAVE_SGI_VC_EXTENSION */ #ifdef HAVE_XF86VMODE_GAMMA static int xf86_gamma_fade (Display *dpy, - Window *black_windows, int seconds, int ticks, + Window *black_windows, int nwindows, + int seconds, int ticks, Bool out_p, Bool clear_windows); #endif /* HAVE_XF86VMODE_GAMMA */ void -fade_screens (Display *dpy, Colormap *cmaps, Window *black_windows, +fade_screens (Display *dpy, Colormap *cmaps, + Window *black_windows, int nwindows, int seconds, int ticks, Bool out_p, Bool clear_windows) { @@ -116,7 +120,8 @@ fade_screens (Display *dpy, Colormap *cmaps, Window *black_windows, #ifdef HAVE_SGI_VC_EXTENSION /* First try to do it by fading the gamma in an SGI-specific way... */ - if (0 == sgi_gamma_fade(dpy, black_windows, seconds, ticks, out_p, + if (0 == sgi_gamma_fade(dpy, black_windows, nwindows, + seconds, ticks, out_p, clear_windows)) ; else @@ -124,7 +129,8 @@ fade_screens (Display *dpy, Colormap *cmaps, Window *black_windows, #ifdef HAVE_XF86VMODE_GAMMA /* Then try to do it by fading the gamma in an XFree86-specific way... */ - if (0 == xf86_gamma_fade(dpy, black_windows, seconds, ticks, out_p, + if (0 == xf86_gamma_fade(dpy, black_windows, nwindows, + seconds, ticks, out_p, clear_windows)) ; else @@ -132,7 +138,8 @@ fade_screens (Display *dpy, Colormap *cmaps, Window *black_windows, /* Else, do it the old-fashioned way, which (somewhat) loses if there are TrueColor windows visible. */ - fade_screens_1 (dpy, cmaps, black_windows, seconds, ticks, + fade_screens_1 (dpy, cmaps, black_windows, nwindows, + seconds, ticks, out_p, clear_windows); /* If we were supposed to be fading in, do so now (we just faded out, @@ -168,7 +175,8 @@ fade_screens (Display *dpy, Colormap *cmaps, Window *black_windows, what is implemented in sgi_gamma_fade(), so we use that if we can. */ static void -fade_screens_1 (Display *dpy, Colormap *cmaps, Window *black_windows, +fade_screens_1 (Display *dpy, Colormap *cmaps, + Window *black_windows, int nwindows, int seconds, int ticks, Bool out_p, Bool clear_windows) { @@ -286,7 +294,7 @@ fade_screens_1 (Display *dpy, Colormap *cmaps, Window *black_windows, installed = True; if (black_windows && !out_p) - for (j = 0; j < nscreens; j++) + for (j = 0; j < nwindows; j++) if (black_windows[j]) { XUnmapWindow (dpy, black_windows[j]); @@ -341,7 +349,7 @@ fade_screens_1 (Display *dpy, Colormap *cmaps, Window *black_windows, */ if (out_p && black_windows) { - for (i = 0; i < nscreens; i++) + for (i = 0; i < nwindows; i++) { if (clear_windows) XClearWindow (dpy, black_windows[i]); @@ -400,7 +408,8 @@ static void sgi_whack_gamma(Display *dpy, int screen, static int sgi_gamma_fade (Display *dpy, - Window *black_windows, int seconds, int ticks, + Window *black_windows, int nwindows, + int seconds, int ticks, Bool out_p, Bool clear_windows) { int steps = seconds * ticks; @@ -472,17 +481,18 @@ sgi_gamma_fade (Display *dpy, way down to 0, then take the windows off the screen. */ if (!out_p) - for (screen = 0; screen < nscreens; screen++) - { + { + for (screen = 0; screen < nscreens; screen++) sgi_whack_gamma(dpy, screen, &info[screen], 0.0); + + for (screen = 0; screen < nwindows; screen++) if (black_windows && black_windows[screen]) { XUnmapWindow (dpy, black_windows[screen]); XClearWindow (dpy, black_windows[screen]); XSync(dpy, False); } - } - + } /* Iterate by steps of the animation... */ for (i = (out_p ? steps : 0); @@ -536,7 +546,7 @@ sgi_gamma_fade (Display *dpy, if (out_p && black_windows) { - for (screen = 0; screen < nscreens; screen++) + for (screen = 0; screen < nwindows; screen++) { if (clear_windows) XClearWindow (dpy, black_windows[screen]); @@ -606,13 +616,20 @@ sgi_whack_gamma(Display *dpy, int screen, struct screen_sgi_gamma_info *info, #include -static Bool xf86_whack_gamma(Display *dpy, int screen, - XF86VidModeGamma *info, float ratio); -static Bool xf86_check_gamma_extension (Display *dpy); +typedef struct { + XF86VidModeGamma vmg; + int size; + unsigned short *r, *g, *b; +} xf86_gamma_info; + +static int xf86_check_gamma_extension (Display *dpy); +static Bool xf86_whack_gamma (Display *dpy, int screen, + xf86_gamma_info *ginfo, float ratio); static int xf86_gamma_fade (Display *dpy, - Window *black_windows, int seconds, int ticks, + Window *black_windows, int nwindows, + int seconds, int ticks, Bool out_p, Bool clear_windows) { int steps = seconds * ticks; @@ -625,27 +642,61 @@ xf86_gamma_fade (Display *dpy, #endif int i, screen; int status = -1; - XF86VidModeGamma *info = 0; + xf86_gamma_info *info = 0; static int ext_ok = -1; /* Only probe the extension once: the answer isn't going to change. */ if (ext_ok == -1) - ext_ok = (xf86_check_gamma_extension (dpy) ? 1 : 0); + ext_ok = xf86_check_gamma_extension (dpy); /* If this server doesn't have the gamma extension, bug out. */ if (ext_ok == 0) goto FAIL; - info = (XF86VidModeGamma *) calloc(nscreens, sizeof(*info)); +# ifndef HAVE_XF86VMODE_GAMMA_RAMP + if (ext_ok == 2) ext_ok = 1; /* server is newer than client! */ +# endif + + info = (xf86_gamma_info *) calloc(nscreens, sizeof(*info)); /* Get the current gamma maps for all screens. Bug out and return -1 if we can't get them for some screen. */ for (screen = 0; screen < nscreens; screen++) { - if (!XF86VidModeGetGamma(dpy, screen, &info[screen])) - goto FAIL; + if (ext_ok == 1) /* only have gamma parameter, not ramps. */ + { + if (!XF86VidModeGetGamma(dpy, screen, &info[screen].vmg)) + goto FAIL; + } +# ifdef HAVE_XF86VMODE_GAMMA_RAMP + else if (ext_ok == 2) /* have ramps */ + { + if (!XF86VidModeGetGammaRampSize(dpy, screen, &info[screen].size)) + goto FAIL; + if (info[screen].size <= 0) + goto FAIL; + + info[screen].r = (unsigned short *) + calloc(info[screen].size, sizeof(unsigned short)); + info[screen].g = (unsigned short *) + calloc(info[screen].size, sizeof(unsigned short)); + info[screen].b = (unsigned short *) + calloc(info[screen].size, sizeof(unsigned short)); + + if (!(info[screen].r && info[screen].g && info[screen].b)) + goto FAIL; + + if (!XF86VidModeGetGammaRamp(dpy, screen, info[screen].size, + info[screen].r, + info[screen].g, + info[screen].b)) + goto FAIL; + } +# endif /* HAVE_XF86VMODE_GAMMA_RAMP */ + else + abort(); } #ifdef GETTIMEOFDAY_TWO_ARGS @@ -658,17 +709,17 @@ xf86_gamma_fade (Display *dpy, way down to 0, then take the windows off the screen. */ if (!out_p) - for (screen = 0; screen < nscreens; screen++) - { + { + for (screen = 0; screen < nscreens; screen++) xf86_whack_gamma(dpy, screen, &info[screen], 0.0); + for (screen = 0; screen < nwindows; screen++) if (black_windows && black_windows[screen]) { XUnmapWindow (dpy, black_windows[screen]); XClearWindow (dpy, black_windows[screen]); XSync(dpy, False); } - } - + } /* Iterate by steps of the animation... */ for (i = (out_p ? steps : 0); @@ -722,7 +773,7 @@ xf86_gamma_fade (Display *dpy, if (out_p && black_windows) { - for (screen = 0; screen < nscreens; screen++) + for (screen = 0; screen < nwindows; screen++) { if (clear_windows) XClearWindow (dpy, black_windows[screen]); @@ -744,35 +795,95 @@ xf86_gamma_fade (Display *dpy, status = 0; FAIL: - if (info) free(info); + if (info) + { + for (screen = 0; screen < nscreens; screen++) + { + if (info[screen].r) free(info[screen].r); + if (info[screen].g) free(info[screen].g); + if (info[screen].b) free(info[screen].b); + } + free(info); + } return status; } -/* VidModeExtension version 2.0 or better is needed to do gamma. */ -# define XF86_VIDMODE_NAME "XFree86-VidModeExtension" -# define XF86_VIDMODE_MIN_MAJOR 2 -# define XF86_VIDMODE_MIN_MINOR 0 +/* This bullshit is needed because the VidMode extension doesn't work + on remote displays -- but if the remote display has the extension + at all, XF86VidModeQueryExtension returns true, and then + XF86VidModeQueryVersion dies with an X error. Thank you XFree, + may I have another. + */ + +static Bool error_handler_hit_p = False; + +static int +ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error) +{ + error_handler_hit_p = True; + return 0; +} static Bool +safe_XF86VidModeQueryVersion (Display *dpy, int *majP, int *minP) +{ + Bool result; + XErrorHandler old_handler; + XSync (dpy, False); + error_handler_hit_p = False; + old_handler = XSetErrorHandler (ignore_all_errors_ehandler); + + result = XF86VidModeQueryVersion (dpy, majP, minP); + + XSync (dpy, False); + XSetErrorHandler (old_handler); + XSync (dpy, False); + + return (error_handler_hit_p + ? False + : result); +} + + + +/* VidModeExtension version 2.0 or better is needed to do gamma. + 2.0 added gamma values; 2.1 added gamma ramps. + */ +# define XF86_VIDMODE_GAMMA_MIN_MAJOR 2 +# define XF86_VIDMODE_GAMMA_MIN_MINOR 0 +# define XF86_VIDMODE_GAMMA_RAMP_MIN_MAJOR 2 +# define XF86_VIDMODE_GAMMA_RAMP_MIN_MINOR 1 + + + +/* Returns 0 if gamma fading not available; 1 if only gamma value setting + is available; 2 if gamma ramps are available. + */ +static int xf86_check_gamma_extension (Display *dpy) { - int op, event, error, major, minor; + int event, error, major, minor; + + if (!XF86VidModeQueryExtension (dpy, &event, &error)) + return 0; /* display doesn't have the extension. */ - if (!XQueryExtension (dpy, XF86_VIDMODE_NAME, &op, &event, &error)) - return False; /* display doesn't have the extension. */ + if (!safe_XF86VidModeQueryVersion (dpy, &major, &minor)) + return 0; /* unable to get version number? */ - if (!XF86VidModeQueryVersion (dpy, &major, &minor)) - return False; /* unable to get version number? */ + if (major < XF86_VIDMODE_GAMMA_MIN_MAJOR || + (major == XF86_VIDMODE_GAMMA_MIN_MAJOR && + minor < XF86_VIDMODE_GAMMA_MIN_MINOR)) + return 0; /* extension is too old for gamma. */ - if (major < XF86_VIDMODE_MIN_MAJOR || - (major == XF86_VIDMODE_MIN_MAJOR && - minor < XF86_VIDMODE_MIN_MINOR)) - return False; /* extension is too old. */ + if (major < XF86_VIDMODE_GAMMA_RAMP_MIN_MAJOR || + (major == XF86_VIDMODE_GAMMA_RAMP_MIN_MAJOR && + minor < XF86_VIDMODE_GAMMA_RAMP_MIN_MINOR)) + return 1; /* extension is too old for gamma ramps. */ /* Copacetic */ - return True; + return 2; } @@ -783,28 +894,58 @@ xf86_check_gamma_extension (Display *dpy) static Bool -xf86_whack_gamma(Display *dpy, int screen, XF86VidModeGamma *info, +xf86_whack_gamma(Display *dpy, int screen, xf86_gamma_info *info, float ratio) { Bool status; - XF86VidModeGamma g2; if (ratio < 0) ratio = 0; if (ratio > 1) ratio = 1; - g2.red = info->red * ratio; - g2.green = info->green * ratio; - g2.blue = info->blue * ratio; + if (info->size == 0) /* we only have a gamma number, not a ramp. */ + { + XF86VidModeGamma g2; + + g2.red = info->vmg.red * ratio; + g2.green = info->vmg.green * ratio; + g2.blue = info->vmg.blue * ratio; # ifdef XF86_MIN_GAMMA - if (g2.red < XF86_MIN_GAMMA) g2.red = XF86_MIN_GAMMA; - if (g2.green < XF86_MIN_GAMMA) g2.green = XF86_MIN_GAMMA; - if (g2.blue < XF86_MIN_GAMMA) g2.blue = XF86_MIN_GAMMA; + if (g2.red < XF86_MIN_GAMMA) g2.red = XF86_MIN_GAMMA; + if (g2.green < XF86_MIN_GAMMA) g2.green = XF86_MIN_GAMMA; + if (g2.blue < XF86_MIN_GAMMA) g2.blue = XF86_MIN_GAMMA; # endif -/* #### printf(" G %4.2f %4.2f\n", ratio, g2.red); */ + status = XF86VidModeSetGamma (dpy, screen, &g2); + } + else + { +# ifdef HAVE_XF86VMODE_GAMMA_RAMP + + unsigned short *r, *g, *b; + int i; + r = (unsigned short *) malloc(info->size * sizeof(unsigned short)); + g = (unsigned short *) malloc(info->size * sizeof(unsigned short)); + b = (unsigned short *) malloc(info->size * sizeof(unsigned short)); + + for (i = 0; i < info->size; i++) + { + r[i] = info->r[i] * ratio; + g[i] = info->g[i] * ratio; + b[i] = info->b[i] * ratio; + } + + status = XF86VidModeSetGammaRamp(dpy, screen, info->size, r, g, b); + + free (r); + free (g); + free (b); + +# else /* !HAVE_XF86VMODE_GAMMA_RAMP */ + abort(); +# endif /* !HAVE_XF86VMODE_GAMMA_RAMP */ + } - status = XF86VidModeSetGamma (dpy, screen, &g2); XSync(dpy, False); return status; }