diff -r 5002d6aeb85c src/video/x11/SDL_x11sym.h --- a/src/video/x11/SDL_x11sym.h Fri Jul 09 17:19:18 2010 +0200 +++ b/src/video/x11/SDL_x11sym.h Sun Aug 15 11:19:34 2010 -0600 @@ -189,6 +189,14 @@ SDL_X11_SYM(XRRScreenSize *,XRRConfigSizes,(XRRScreenConfiguration *config, int *nsizes),(config,nsizes),return) SDL_X11_SYM(Status,XRRSetScreenConfig,(Display *dpy, XRRScreenConfiguration *config, Drawable draw, int size_index, Rotation rotation, Time timestamp),(dpy,config,draw,size_index,rotation,timestamp),return) SDL_X11_SYM(void,XRRFreeScreenConfigInfo,(XRRScreenConfiguration *config),(config),) +SDL_X11_SYM(XRRScreenResources *,XRRGetScreenResources,(Display *dpy, Window window),(dpy,window),return) +SDL_X11_SYM(XRRScreenResources *,XRRGetScreenResourcesCurrent,(Display *dpy, Window window),(dpy,window),return) +SDL_X11_SYM(void,XRRFreeScreenResources,(XRRScreenResources *resources),(resources),) +SDL_X11_SYM(int,XRRGetCrtcGammaSize,(Display *dpy, RRCrtc crtc),(dpy,crtc),return) +SDL_X11_SYM(XRRCrtcGamma *,XRRAllocGamma,(int size),(size),return) +SDL_X11_SYM(void,XRRFreeGamma,(XRRCrtcGamma *gamma),(gamma),) +SDL_X11_SYM(XRRCrtcGamma *,XRRGetCrtcGamma,(Display *dpy, RRCrtc crtc),(dpy,crtc),return) +SDL_X11_SYM(void,XRRSetCrtcGamma,(Display *dpy, RRCrtc crtc, XRRCrtcGamma *gamma),(dpy,crtc,gamma),) #endif /* end of SDL_x11sym.h ... */ diff -r 5002d6aeb85c src/video/x11/SDL_x11video.c --- a/src/video/x11/SDL_x11video.c Fri Jul 09 17:19:18 2010 +0200 +++ b/src/video/x11/SDL_x11video.c Sun Aug 15 11:19:34 2010 -0600 @@ -65,6 +65,9 @@ static void X11_UpdateMouse(_THIS); static int X11_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); +static void X11_FreeSavedGammaRamp(_THIS); +static int X11_RestoreGammaRamp(_THIS); +static int X11_SaveGammaRamp(_THIS); static int X11_SetGammaRamp(_THIS, Uint16 *ramp); static void X11_VideoQuit(_THIS); @@ -667,6 +670,7 @@ if ( this->hidden->depth == 32 ) { vformat->Amask = (0xFFFFFFFF & ~(vformat->Rmask|vformat->Gmask|vformat->Bmask)); } + X11_SaveGammaRamp(this); X11_SaveVidModeGamma(this); /* Allow environment override of screensaver disable. */ @@ -1432,10 +1436,248 @@ return nrej == 0; } +void X11_FreeSavedGammaRamp(_THIS) +{ + int i; + +#if SDL_VIDEO_DRIVER_X11_XRANDR + if (gamma_ramp_saved_xrr) { + for ( i=0; i= 103) { + resrc = XRRGetScreenResourcesCurrent(SDL_Display, SDL_Root); + } else { + resrc = XRRGetScreenResources(SDL_Display, SDL_Root); + } + + if (resrc != NULL) { + gamma_ramp_saved_xrr_size = resrc->ncrtc; + gamma_ramp_saved_xrr = SDL_malloc( + sizeof(gamma_ramp_saved_xrr[0]) * + gamma_ramp_saved_xrr_size); + } + + for ( i=0; resrc != NULL && incrtc; ++i ) { + gamma_ramp_saved_xrr[i] = XRRGetCrtcGamma(SDL_Display, + resrc->crtcs[i]); + } + + if (resrc != NULL) { + XRRFreeScreenResources(resrc); + return(0); + } + } +#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */ + +#if SDL_VIDEO_DRIVER_X11_VIDMODE + if (use_vidmode >= 200 && gamma_ramp_size == 0) { + succeeded = SDL_NAME(XF86VidModeGetGammaRampSize)( + SDL_Display, SDL_Screen, + &gamma_ramp_size); + + if (!succeeded) { + gamma_ramp_size = 0; + } + } + + if (use_vidmode >= 200 && gamma_ramp_size > 0) { + gamma_ramp_saved_vm = SDL_malloc( + sizeof(gamma_ramp_saved_vm[0]) * + 3 * gamma_ramp_size); + + succeeded = SDL_NAME(XF86VidModeGetGammaRamp)( + SDL_Display, SDL_Screen, + gamma_ramp_size, + gamma_ramp_saved_vm + 0*gamma_ramp_size, + gamma_ramp_saved_vm + 1*gamma_ramp_size, + gamma_ramp_saved_vm + 2*gamma_ramp_size); + + if (!succeeded) { + SDL_free(gamma_ramp_saved_vm); + gamma_ramp_saved_vm = NULL; + } else { + return(0); + } + } +#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */ + + return(-1); +} + +int X11_RestoreGammaRamp(_THIS) +{ + int i; + Bool succeeded; + +#if SDL_VIDEO_DRIVER_X11_XRANDR + if (use_xrandr && gamma_ramp_saved_xrr != NULL) { + XRRScreenResources *resrc; + + if (use_xrandr >= 103) { + resrc = XRRGetScreenResourcesCurrent(SDL_Display, SDL_Root); + } else { + resrc = XRRGetScreenResources(SDL_Display, SDL_Root); + } + + for ( i=0; resrc != NULL && incrtc && icrtcs[i], + gamma_ramp_saved_xrr[i]); + } + + if (resrc != NULL) { + XRRFreeScreenResources(resrc); + return(0); + } + } +#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */ + +#if SDL_VIDEO_DRIVER_X11_VIDMODE + if (use_vidmode >= 200 && gamma_ramp_saved_vm != NULL) { + succeeded = SDL_NAME(XF86VidModeSetGammaRamp)( + SDL_Display, SDL_Screen, + gamma_ramp_size, + gamma_ramp_saved_vm + 0*gamma_ramp_size, + gamma_ramp_saved_vm + 1*gamma_ramp_size, + gamma_ramp_saved_vm + 2*gamma_ramp_size); + + if (succeeded) + return(0); + } +#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */ + + return(-1); +} + int X11_SetGammaRamp(_THIS, Uint16 *ramp) { - int i, ncolors; + int i, j, ncolors; XColor xcmap[256]; + Bool succeeded; + +#if SDL_VIDEO_DRIVER_X11_XRANDR + if (use_xrandr) { + XRRCrtcGamma *gamma = NULL; + int gammasize = 0; + XRRScreenResources *resrc; + + if (use_xrandr >= 103) { + resrc = XRRGetScreenResourcesCurrent(SDL_Display, SDL_Root); + } else { + resrc = XRRGetScreenResources(SDL_Display, SDL_Root); + } + + /* Implementation Note: + * We try to make few assumptions here, notably: + * - Ramp size can vary between crtcs + * (which can happen when using multiple video cards) + * - Ramp size (by index) can vary between calls + * (which can happen if the window is moved to a new crtc) + */ + for ( i=0; resrc != NULL && incrtc; ++i ) { + int crtcgs; + + crtcgs = XRRGetCrtcGammaSize(SDL_Display, + resrc->crtcs[i]); + if (crtcgs != gammasize) { + /* Size in this CRTC differs from last */ + if (gamma != NULL) { + XRRFreeGamma(gamma); + } + + gammasize = crtcgs; + gamma = XRRAllocGamma(gammasize); + + for ( j=0; jred[j] = + ramp[0*256+j*256/gammasize]; + gamma->green[j] = + ramp[1*256+j*256/gammasize]; + gamma->blue[j] = + ramp[2*256+j*256/gammasize]; + } + } + + XRRSetCrtcGamma(SDL_Display, resrc->crtcs[i], gamma); + } + + if (gamma != NULL) { + XRRFreeGamma(gamma); + } + + if (resrc != NULL) { + XRRFreeScreenResources(resrc); + return(0); + } + } +#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */ + +#if SDL_VIDEO_DRIVER_X11_VIDMODE + if (use_vidmode >= 200 && gamma_ramp_size == 0) { + succeeded = SDL_NAME(XF86VidModeGetGammaRampSize)( + SDL_Display, SDL_Screen, + &gamma_ramp_size); + + if (!succeeded) { + gamma_ramp_size = 0; + } + } + + if (use_vidmode >= 200 && gamma_ramp_size > 0) { + Uint16 *sizedramp; + + if (gamma_ramp_size == 256) { + sizedramp = ramp; + } else { + sizedramp = SDL_stack_alloc(Uint16, 3*gamma_ramp_size); + if (sizedramp == NULL) { + SDL_OutOfMemory(); + return(-1); + } + + for ( i=0; iclass != DirectColor ) { @@ -1507,7 +1749,9 @@ /* Restore gamma settings if they've changed */ if ( SDL_GetAppState() & SDL_APPACTIVE ) { X11_SwapVidModeGamma(this); + X11_RestoreGammaRamp(this); } + X11_FreeSavedGammaRamp(this); /* Free that blank cursor */ if ( SDL_BlankCursor != NULL ) { diff -r 5002d6aeb85c src/video/x11/SDL_x11video.h --- a/src/video/x11/SDL_x11video.h Fri Jul 09 17:19:18 2010 +0200 +++ b/src/video/x11/SDL_x11video.h Sun Aug 15 11:19:34 2010 -0600 @@ -119,12 +119,16 @@ XRRScreenConfiguration* screen_config; int saved_size_id; Rotation saved_rotation; + XRRCrtcGamma** gamma_ramp_saved_xrr; + int gamma_ramp_saved_xrr_size; #endif #if SDL_VIDEO_DRIVER_X11_VIDMODE SDL_NAME(XF86VidModeModeInfo) saved_mode; struct { int x, y; } saved_view; + int gamma_ramp_size; + Uint16* gamma_ramp_saved_vm; #endif #if SDL_VIDEO_DRIVER_X11_XME /* XiG XME fullscreen */ XiGMiscResolutionInfo saved_res; @@ -182,6 +186,10 @@ #define mouse_accel (this->hidden->mouse_accel) #define mouse_relative (this->hidden->mouse_relative) #define SDL_modelist (this->hidden->modelist) +#define gamma_ramp_size (this->hidden->gamma_ramp_size) +#define gamma_ramp_saved_vm (this->hidden->gamma_ramp_saved_vm) +#define gamma_ramp_saved_xrr (this->hidden->gamma_ramp_saved_xrr) +#define gamma_ramp_saved_xrr_size (this->hidden->gamma_ramp_saved_xrr_size) #define xinerama_info (this->hidden->xinerama_info) #define saved_mode (this->hidden->saved_mode) #define saved_view (this->hidden->saved_view)