Gamma support is back!
authorSam Lantinga <slouken@libsdl.org>
Fri, 11 Mar 2011 08:49:20 -0800
changeset 5466006883d5fa51
parent 5465 46bd121b04a2
child 5467 1ca154e8d6a6
Gamma support is back!

New API functions:
SDL_SetWindowBrightness()
SDL_GetWindowBrightness()
SDL_SetWindowGammaRamp()
SDL_GetWindowGammaRamp()
SDL_CalculateGammaRamp()
VisualC/tests/testgamma/testgamma_VS2008.vcproj
VisualC/tests/testgamma/testgamma_VS2010.vcxproj
include/SDL_pixels.h
include/SDL_video.h
src/SDL_compat.c
src/video/SDL_pixels.c
src/video/SDL_sysvideo.h
src/video/SDL_video.c
src/video/cocoa/SDL_cocoavideo.m
src/video/cocoa/SDL_cocoawindow.h
src/video/cocoa/SDL_cocoawindow.m
src/video/windows/SDL_windowsvideo.c
src/video/windows/SDL_windowswindow.c
src/video/windows/SDL_windowswindow.h
src/video/x11/SDL_x11modes.c
src/video/x11/SDL_x11video.c
src/video/x11/SDL_x11video.h
src/video/x11/SDL_x11window.c
src/video/x11/SDL_x11window.h
test/Makefile.in
test/testgamma.c
     1.1 --- a/VisualC/tests/testgamma/testgamma_VS2008.vcproj	Thu Mar 10 01:03:43 2011 -0800
     1.2 +++ b/VisualC/tests/testgamma/testgamma_VS2008.vcproj	Fri Mar 11 08:49:20 2011 -0800
     1.3 @@ -103,8 +103,8 @@
     1.4  			/>
     1.5  			<Tool
     1.6  				Name="VCPostBuildEventTool"
     1.7 -				Description="Copy SDL"
     1.8 -				CommandLine="copy $(SolutionDir)\SDL\$(ConfigurationName)\SDL.dll $(TargetDir)\SDL.dll"
     1.9 +				Description="Copy SDL and data files"
    1.10 +				CommandLine="copy $(SolutionDir)\SDL\$(ConfigurationName)\SDL.dll $(TargetDir)\SDL.dll&#x0D;&#x0A;copy $(SolutionDir)\..\test\sample.bmp $(ProjectDir)\sample.bmp"
    1.11  			/>
    1.12  		</Configuration>
    1.13  		<Configuration
    1.14 @@ -195,8 +195,8 @@
    1.15  			/>
    1.16  			<Tool
    1.17  				Name="VCPostBuildEventTool"
    1.18 -				Description="Copy SDL"
    1.19 -				CommandLine="copy $(SolutionDir)\SDL\$(ConfigurationName)\SDL.dll $(TargetDir)\SDL.dll"
    1.20 +				Description="Copy SDL and data files"
    1.21 +				CommandLine="copy $(SolutionDir)\SDL\$(ConfigurationName)\SDL.dll $(TargetDir)\SDL.dll&#x0D;&#x0A;copy $(SolutionDir)\..\test\sample.bmp $(ProjectDir)\sample.bmp"
    1.22  			/>
    1.23  		</Configuration>
    1.24  	</Configurations>
     2.1 --- a/VisualC/tests/testgamma/testgamma_VS2010.vcxproj	Thu Mar 10 01:03:43 2011 -0800
     2.2 +++ b/VisualC/tests/testgamma/testgamma_VS2010.vcxproj	Fri Mar 11 08:49:20 2011 -0800
     2.3 @@ -82,10 +82,11 @@
     2.4        <SubSystem>Windows</SubSystem>
     2.5      </Link>
     2.6      <PostBuildEvent>
     2.7 -      <Command>copy $(SolutionDir)\SDL\$(ConfigurationName)\SDL.dll $(TargetDir)\SDL.dll</Command>
     2.8 +      <Command>copy $(SolutionDir)\SDL\$(ConfigurationName)\SDL.dll $(TargetDir)\SDL.dll
     2.9 +copy $(SolutionDir)\..\test\sample.bmp $(ProjectDir)\sample.bmp</Command>
    2.10      </PostBuildEvent>
    2.11      <PostBuildEvent>
    2.12 -      <Message>Copy SDL</Message>
    2.13 +      <Message>Copy SDL and data files</Message>
    2.14      </PostBuildEvent>
    2.15    </ItemDefinitionGroup>
    2.16    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    2.17 @@ -125,10 +126,11 @@
    2.18        <SubSystem>Windows</SubSystem>
    2.19      </Link>
    2.20      <PostBuildEvent>
    2.21 -      <Command>copy $(SolutionDir)\SDL\$(ConfigurationName)\SDL.dll $(TargetDir)\SDL.dll</Command>
    2.22 +      <Command>copy $(SolutionDir)\SDL\$(ConfigurationName)\SDL.dll $(TargetDir)\SDL.dll
    2.23 +copy $(SolutionDir)\..\test\sample.bmp $(ProjectDir)\sample.bmp</Command>
    2.24      </PostBuildEvent>
    2.25      <PostBuildEvent>
    2.26 -      <Message>Copy SDL</Message>
    2.27 +      <Message>Copy SDL and data files</Message>
    2.28      </PostBuildEvent>
    2.29    </ItemDefinitionGroup>
    2.30    <ItemGroup>
     3.1 --- a/include/SDL_pixels.h	Thu Mar 10 01:03:43 2011 -0800
     3.2 +++ b/include/SDL_pixels.h	Fri Mar 11 08:49:20 2011 -0800
     3.3 @@ -405,6 +405,12 @@
     3.4                                           Uint8 * r, Uint8 * g, Uint8 * b,
     3.5                                           Uint8 * a);
     3.6  
     3.7 +/**
     3.8 + *  \brief Calculate a 256 entry gamma ramp for a gamma value.
     3.9 + */
    3.10 +extern DECLSPEC void SDLCALL SDL_CalculateGammaRamp(float gamma, Uint16 * ramp);
    3.11 +
    3.12 +
    3.13  /* Ends C function definitions when using C++ */
    3.14  #ifdef __cplusplus
    3.15  /* *INDENT-OFF* */
     4.1 --- a/include/SDL_video.h	Thu Mar 10 01:03:43 2011 -0800
     4.2 +++ b/include/SDL_video.h	Fri Mar 11 08:49:20 2011 -0800
     4.3 @@ -605,6 +605,66 @@
     4.4  extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowGrab(SDL_Window * window);
     4.5  
     4.6  /**
     4.7 + *  \brief Set the brightness (gamma correction) for a window.
     4.8 + *  
     4.9 + *  \return 0 on success, or -1 if setting the brightness isn't supported.
    4.10 + *  
    4.11 + *  \sa SDL_GetWindowBrightness()
    4.12 + *  \sa SDL_SetWindowGammaRamp()
    4.13 + */
    4.14 +extern DECLSPEC int SDLCALL SDL_SetWindowBrightness(SDL_Window * window, float brightness);
    4.15 +
    4.16 +/**
    4.17 + *  \brief Get the brightness (gamma correction) for a window.
    4.18 + *  
    4.19 + *  \return The last brightness value passed to SDL_SetWindowBrightness()
    4.20 + *  
    4.21 + *  \sa SDL_SetWindowBrightness()
    4.22 + */
    4.23 +extern DECLSPEC float SDLCALL SDL_GetWindowBrightness(SDL_Window * window);
    4.24 +
    4.25 +/**
    4.26 + *  \brief Set the gamma ramp for a window.
    4.27 + *  
    4.28 + *  \param red The translation table for the red channel, or NULL.
    4.29 + *  \param green The translation table for the green channel, or NULL.
    4.30 + *  \param blue The translation table for the blue channel, or NULL.
    4.31 + *  
    4.32 + *  \return 0 on success, or -1 if gamma ramps are unsupported.
    4.33 + *  
    4.34 + *  Set the gamma translation table for the red, green, and blue channels
    4.35 + *  of the video hardware.  Each table is an array of 256 16-bit quantities,
    4.36 + *  representing a mapping between the input and output for that channel.
    4.37 + *  The input is the index into the array, and the output is the 16-bit
    4.38 + *  gamma value at that index, scaled to the output color precision.
    4.39 + *
    4.40 + *  \sa SDL_SetWindowGammaRamp()
    4.41 + */
    4.42 +extern DECLSPEC int SDLCALL SDL_SetWindowGammaRamp(SDL_Window * window,
    4.43 +                                                   const Uint16 * red,
    4.44 +                                                   const Uint16 * green,
    4.45 +                                                   const Uint16 * blue);
    4.46 +
    4.47 +/**
    4.48 + *  \brief Get the gamma ramp for a window.
    4.49 + *  
    4.50 + *  \param red   A pointer to a 256 element array of 16-bit quantities to hold 
    4.51 + *               the translation table for the red channel, or NULL.
    4.52 + *  \param green A pointer to a 256 element array of 16-bit quantities to hold 
    4.53 + *               the translation table for the green channel, or NULL.
    4.54 + *  \param blue  A pointer to a 256 element array of 16-bit quantities to hold 
    4.55 + *               the translation table for the blue channel, or NULL.
    4.56 + *   
    4.57 + *  \return 0 on success, or -1 if gamma ramps are unsupported.
    4.58 + *  
    4.59 + *  \sa SDL_SetWindowGammaRamp()
    4.60 + */
    4.61 +extern DECLSPEC int SDLCALL SDL_GetWindowGammaRamp(SDL_Window * window,
    4.62 +                                                   Uint16 * red,
    4.63 +                                                   Uint16 * green,
    4.64 +                                                   Uint16 * blue);
    4.65 +
    4.66 +/**
    4.67   *  \brief Destroy a window.
    4.68   */
    4.69  extern DECLSPEC void SDLCALL SDL_DestroyWindow(SDL_Window * window);
     5.1 --- a/src/SDL_compat.c	Thu Mar 10 01:03:43 2011 -0800
     5.2 +++ b/src/SDL_compat.c	Fri Mar 11 08:49:20 2011 -0800
     5.3 @@ -1702,22 +1702,34 @@
     5.4  int
     5.5  SDL_SetGamma(float red, float green, float blue)
     5.6  {
     5.7 -    SDL_Unsupported();
     5.8 -    return -1;
     5.9 +    Uint16 red_ramp[256];
    5.10 +    Uint16 green_ramp[256];
    5.11 +    Uint16 blue_ramp[256];
    5.12 +
    5.13 +    SDL_CalculateGammaRamp(red, red_ramp);
    5.14 +    if (green == red) {
    5.15 +        SDL_memcpy(green_ramp, red_ramp, sizeof(red_ramp));
    5.16 +    } else {
    5.17 +        SDL_CalculateGammaRamp(green, green_ramp);
    5.18 +    }
    5.19 +    if (blue == red) {
    5.20 +        SDL_memcpy(blue_ramp, red_ramp, sizeof(red_ramp));
    5.21 +    } else {
    5.22 +        SDL_CalculateGammaRamp(blue, blue_ramp);
    5.23 +    }
    5.24 +    return SDL_SetWindowGammaRamp(SDL_VideoWindow, red_ramp, green_ramp, blue_ramp);
    5.25  }
    5.26  
    5.27  int
    5.28  SDL_SetGammaRamp(const Uint16 * red, const Uint16 * green, const Uint16 * blue)
    5.29  {
    5.30 -    SDL_Unsupported();
    5.31 -    return -1;
    5.32 +    return SDL_SetWindowGammaRamp(SDL_VideoWindow, red, green, blue);
    5.33  }
    5.34  
    5.35  int
    5.36  SDL_GetGammaRamp(Uint16 * red, Uint16 * green, Uint16 * blue)
    5.37  {
    5.38 -    SDL_Unsupported();
    5.39 -    return -1;
    5.40 +    return SDL_GetWindowGammaRamp(SDL_VideoWindow, red, green, blue);
    5.41  }
    5.42  
    5.43  int
     6.1 --- a/src/video/SDL_pixels.c	Thu Mar 10 01:03:43 2011 -0800
     6.2 +++ b/src/video/SDL_pixels.c	Fri Mar 11 08:49:20 2011 -0800
     6.3 @@ -1041,4 +1041,36 @@
     6.4      }
     6.5  }
     6.6  
     6.7 +void
     6.8 +SDL_CalculateGammaRamp(float gamma, Uint16 * ramp)
     6.9 +{
    6.10 +    int i;
    6.11 +
    6.12 +    /* 0.0 gamma is all black */
    6.13 +    if (gamma <= 0.0f) {
    6.14 +        for (i = 0; i < 256; ++i) {
    6.15 +            ramp[i] = 0;
    6.16 +        }
    6.17 +        return;
    6.18 +    } else if (gamma == 1.0f) {
    6.19 +        /* 1.0 gamma is identity */
    6.20 +        for (i = 0; i < 256; ++i) {
    6.21 +            ramp[i] = (i << 8) | i;
    6.22 +        }
    6.23 +        return;
    6.24 +    } else {
    6.25 +        /* Calculate a real gamma ramp */
    6.26 +        int value;
    6.27 +        gamma = 1.0f / gamma;
    6.28 +        for (i = 0; i < 256; ++i) {
    6.29 +            value =
    6.30 +                (int) (SDL_pow((double) i / 256.0, gamma) * 65535.0 + 0.5);
    6.31 +            if (value > 65535) {
    6.32 +                value = 65535;
    6.33 +            }
    6.34 +            ramp[i] = (Uint16) value;
    6.35 +        }
    6.36 +    }
    6.37 +}
    6.38 +
    6.39  /* vi: set ts=4 sw=4 expandtab: */
     7.1 --- a/src/video/SDL_sysvideo.h	Thu Mar 10 01:03:43 2011 -0800
     7.2 +++ b/src/video/SDL_sysvideo.h	Fri Mar 11 08:49:20 2011 -0800
     7.3 @@ -81,6 +81,10 @@
     7.4  
     7.5      SDL_DisplayMode fullscreen_mode;
     7.6      
     7.7 +    float brightness;
     7.8 +    Uint16 *gamma;
     7.9 +    Uint16 *saved_gamma;        /* (just offset into gamma) */
    7.10 +
    7.11      SDL_Surface *surface;
    7.12      SDL_bool surface_valid;
    7.13  
    7.14 @@ -184,6 +188,8 @@
    7.15      void (*MinimizeWindow) (_THIS, SDL_Window * window);
    7.16      void (*RestoreWindow) (_THIS, SDL_Window * window);
    7.17      void (*SetWindowFullscreen) (_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
    7.18 +    int (*SetWindowGammaRamp) (_THIS, SDL_Window * window, const Uint16 * ramp);
    7.19 +    int (*GetWindowGammaRamp) (_THIS, SDL_Window * window, Uint16 * ramp);
    7.20      void (*SetWindowGrab) (_THIS, SDL_Window * window);
    7.21      void (*DestroyWindow) (_THIS, SDL_Window * window);
    7.22      int (*CreateWindowFramebuffer) (_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch);
     8.1 --- a/src/video/SDL_video.c	Thu Mar 10 01:03:43 2011 -0800
     8.2 +++ b/src/video/SDL_video.c	Fri Mar 11 08:49:20 2011 -0800
     8.3 @@ -1161,6 +1161,7 @@
     8.4          }
     8.5      }
     8.6      window->flags = ((flags & CREATE_FLAGS) | SDL_WINDOW_HIDDEN);
     8.7 +    window->brightness = 1.0f;
     8.8      window->next = _this->windows;
     8.9      if (_this->windows) {
    8.10          _this->windows->prev = window;
    8.11 @@ -1193,6 +1194,7 @@
    8.12      window->magic = &_this->window_magic;
    8.13      window->id = _this->next_object_id++;
    8.14      window->flags = SDL_WINDOW_FOREIGN;
    8.15 +    window->brightness = 1.0f;
    8.16      window->next = _this->windows;
    8.17      if (_this->windows) {
    8.18          _this->windows->prev = window;
    8.19 @@ -1675,6 +1677,110 @@
    8.20      return _this->UpdateWindowFramebuffer(_this, window, rects, numrects);
    8.21  }
    8.22  
    8.23 +int
    8.24 +SDL_SetWindowBrightness(SDL_Window * window, float brightness)
    8.25 +{
    8.26 +    Uint16 ramp[256];
    8.27 +    int status;
    8.28 +
    8.29 +    CHECK_WINDOW_MAGIC(window, -1);
    8.30 +
    8.31 +    SDL_CalculateGammaRamp(brightness, ramp);
    8.32 +    status = SDL_SetWindowGammaRamp(window, ramp, ramp, ramp);
    8.33 +    if (status == 0) {
    8.34 +        window->brightness = brightness;
    8.35 +    }
    8.36 +    return status;
    8.37 +}
    8.38 +
    8.39 +float
    8.40 +SDL_GetWindowBrightness(SDL_Window * window)
    8.41 +{
    8.42 +    CHECK_WINDOW_MAGIC(window, 1.0f);
    8.43 +
    8.44 +    return window->brightness;
    8.45 +}
    8.46 +
    8.47 +int
    8.48 +SDL_SetWindowGammaRamp(SDL_Window * window, const Uint16 * red,
    8.49 +                                            const Uint16 * green,
    8.50 +                                            const Uint16 * blue)
    8.51 +{
    8.52 +    CHECK_WINDOW_MAGIC(window, -1);
    8.53 +
    8.54 +    if (!_this->SetWindowGammaRamp) {
    8.55 +        SDL_Unsupported();
    8.56 +        return -1;
    8.57 +    }
    8.58 +
    8.59 +    if (!window->gamma) {
    8.60 +        if (SDL_GetWindowGammaRamp(window, NULL, NULL, NULL) < 0) {
    8.61 +            return -1;
    8.62 +        }
    8.63 +    }
    8.64 +
    8.65 +    if (red) {
    8.66 +        SDL_memcpy(&window->gamma[0*256], red, 256*sizeof(Uint16));
    8.67 +    }
    8.68 +    if (green) {
    8.69 +        SDL_memcpy(&window->gamma[1*256], green, 256*sizeof(Uint16));
    8.70 +    }
    8.71 +    if (blue) {
    8.72 +        SDL_memcpy(&window->gamma[2*256], blue, 256*sizeof(Uint16));
    8.73 +    }
    8.74 +    if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
    8.75 +        return _this->SetWindowGammaRamp(_this, window, window->gamma);
    8.76 +    } else {
    8.77 +        return 0;
    8.78 +    }
    8.79 +}
    8.80 +
    8.81 +int
    8.82 +SDL_GetWindowGammaRamp(SDL_Window * window, Uint16 * red,
    8.83 +                                            Uint16 * green,
    8.84 +                                            Uint16 * blue)
    8.85 +{
    8.86 +    CHECK_WINDOW_MAGIC(window, -1);
    8.87 +
    8.88 +    if (!window->gamma) {
    8.89 +        int i;
    8.90 +
    8.91 +        window->gamma = (Uint16 *)SDL_malloc(256*6*sizeof(Uint16));
    8.92 +        if (!window->gamma) {
    8.93 +            SDL_OutOfMemory();
    8.94 +            return -1;
    8.95 +        }
    8.96 +        window->saved_gamma = window->gamma + 3*256;
    8.97 +
    8.98 +        if (_this->GetWindowGammaRamp) {
    8.99 +            if (_this->GetWindowGammaRamp(_this, window, window->gamma) < 0) {
   8.100 +                return -1;
   8.101 +            }
   8.102 +        } else {
   8.103 +            /* Create an identity gamma ramp */
   8.104 +            for (i = 0; i < 256; ++i) {
   8.105 +                Uint16 value = (Uint16)((i << 8) | i);
   8.106 +
   8.107 +                window->gamma[0*256+i] = value;
   8.108 +                window->gamma[1*256+i] = value;
   8.109 +                window->gamma[2*256+i] = value;
   8.110 +            }
   8.111 +        }
   8.112 +        SDL_memcpy(window->saved_gamma, window->gamma, 3*256*sizeof(Uint16));
   8.113 +    }
   8.114 +
   8.115 +    if (red) {
   8.116 +        SDL_memcpy(red, &window->gamma[0*256], 256*sizeof(Uint16));
   8.117 +    }
   8.118 +    if (green) {
   8.119 +        SDL_memcpy(green, &window->gamma[1*256], 256*sizeof(Uint16));
   8.120 +    }
   8.121 +    if (blue) {
   8.122 +        SDL_memcpy(blue, &window->gamma[2*256], 256*sizeof(Uint16));
   8.123 +    }
   8.124 +    return 0;
   8.125 +}
   8.126 +
   8.127  static void
   8.128  SDL_UpdateWindowGrab(SDL_Window * window)
   8.129  {
   8.130 @@ -1702,7 +1808,7 @@
   8.131  SDL_bool
   8.132  SDL_GetWindowGrab(SDL_Window * window)
   8.133  {
   8.134 -    CHECK_WINDOW_MAGIC(window, 0);
   8.135 +    CHECK_WINDOW_MAGIC(window, SDL_FALSE);
   8.136  
   8.137      return ((window->flags & SDL_WINDOW_INPUT_GRABBED) != 0);
   8.138  }
   8.139 @@ -1745,8 +1851,12 @@
   8.140  void
   8.141  SDL_OnWindowFocusGained(SDL_Window * window)
   8.142  {
   8.143 -    if ((window->flags & (SDL_WINDOW_INPUT_GRABBED | SDL_WINDOW_FULLSCREEN))
   8.144 -        && _this->SetWindowGrab) {
   8.145 +    if (window->gamma && _this->SetWindowGammaRamp) {
   8.146 +        _this->SetWindowGammaRamp(_this, window, window->gamma);
   8.147 +    }
   8.148 +
   8.149 +    if ((window->flags & SDL_WINDOW_INPUT_GRABBED | SDL_WINDOW_FULLSCREEN) &&
   8.150 +        _this->SetWindowGrab) {
   8.151          _this->SetWindowGrab(_this, window);
   8.152      }
   8.153  }
   8.154 @@ -1754,16 +1864,19 @@
   8.155  void
   8.156  SDL_OnWindowFocusLost(SDL_Window * window)
   8.157  {
   8.158 -    /* If we're fullscreen on a single-head system and lose focus, minimize */
   8.159 -    if ((window->flags & SDL_WINDOW_FULLSCREEN) &&
   8.160 -        _this->num_displays == 1) {
   8.161 -        SDL_MinimizeWindow(window);
   8.162 +    if (window->gamma && _this->SetWindowGammaRamp) {
   8.163 +        _this->SetWindowGammaRamp(_this, window, window->saved_gamma);
   8.164      }
   8.165  
   8.166 -    if ((window->flags & (SDL_WINDOW_INPUT_GRABBED | SDL_WINDOW_FULLSCREEN))
   8.167 -        && _this->SetWindowGrab) {
   8.168 +    if ((window->flags & SDL_WINDOW_INPUT_GRABBED | SDL_WINDOW_FULLSCREEN) &&
   8.169 +        _this->SetWindowGrab) {
   8.170          _this->SetWindowGrab(_this, window);
   8.171      }
   8.172 +
   8.173 +    /* If we're fullscreen on a single-head system and lose focus, minimize */
   8.174 +    if ((window->flags & SDL_WINDOW_FULLSCREEN) && _this->num_displays == 1) {
   8.175 +        SDL_MinimizeWindow(window);
   8.176 +    }
   8.177  }
   8.178  
   8.179  SDL_Window *
   8.180 @@ -1818,6 +1931,9 @@
   8.181      if (window->title) {
   8.182          SDL_free(window->title);
   8.183      }
   8.184 +    if (window->gamma) {
   8.185 +        SDL_free(window->gamma);
   8.186 +    }
   8.187      while (window->data) {
   8.188          SDL_WindowUserData *data = window->data;
   8.189  
     9.1 --- a/src/video/cocoa/SDL_cocoavideo.m	Thu Mar 10 01:03:43 2011 -0800
     9.2 +++ b/src/video/cocoa/SDL_cocoavideo.m	Fri Mar 11 08:49:20 2011 -0800
     9.3 @@ -93,6 +93,8 @@
     9.4      device->MinimizeWindow = Cocoa_MinimizeWindow;
     9.5      device->RestoreWindow = Cocoa_RestoreWindow;
     9.6      device->SetWindowFullscreen = Cocoa_SetWindowFullscreen;
     9.7 +    device->SetWindowGammaRamp = Cocoa_SetWindowGammaRamp;
     9.8 +    device->GetWindowGammaRamp = Cocoa_GetWindowGammaRamp;
     9.9      device->SetWindowGrab = Cocoa_SetWindowGrab;
    9.10      device->DestroyWindow = Cocoa_DestroyWindow;
    9.11      device->GetWindowWMInfo = Cocoa_GetWindowWMInfo;
    10.1 --- a/src/video/cocoa/SDL_cocoawindow.h	Thu Mar 10 01:03:43 2011 -0800
    10.2 +++ b/src/video/cocoa/SDL_cocoawindow.h	Fri Mar 11 08:49:20 2011 -0800
    10.3 @@ -104,6 +104,8 @@
    10.4  extern void Cocoa_MinimizeWindow(_THIS, SDL_Window * window);
    10.5  extern void Cocoa_RestoreWindow(_THIS, SDL_Window * window);
    10.6  extern void Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
    10.7 +extern int Cocoa_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp);
    10.8 +extern int Cocoa_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp);
    10.9  extern void Cocoa_SetWindowGrab(_THIS, SDL_Window * window);
   10.10  extern void Cocoa_DestroyWindow(_THIS, SDL_Window * window);
   10.11  extern SDL_bool Cocoa_GetWindowWMInfo(_THIS, SDL_Window * window,
    11.1 --- a/src/video/cocoa/SDL_cocoawindow.m	Thu Mar 10 01:03:43 2011 -0800
    11.2 +++ b/src/video/cocoa/SDL_cocoawindow.m	Fri Mar 11 08:49:20 2011 -0800
    11.3 @@ -856,7 +856,58 @@
    11.4      [pool release];
    11.5  }
    11.6  
    11.7 -NSPoint origin;
    11.8 +int
    11.9 +Cocoa_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp)
   11.10 +{
   11.11 +    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
   11.12 +    CGDirectDisplayID display_id = ((SDL_DisplayData *)display->driverdata)->display;
   11.13 +    const uint32_t tableSize = 256;
   11.14 +    CGGammaValue redTable[tableSize];
   11.15 +    CGGammaValue greenTable[tableSize];
   11.16 +    CGGammaValue blueTable[tableSize];
   11.17 +    uint32_t i;
   11.18 +    float inv65535 = 1.0f / 65535.0f;
   11.19 +
   11.20 +    /* Extract gamma values into separate tables, convert to floats between 0.0 and 1.0 */
   11.21 +    for (i = 0; i < 256; i++) {
   11.22 +        redTable[i] = ramp[0*256+i] * inv65535;
   11.23 +        greenTable[i] = ramp[1*256+i] * inv65535;
   11.24 +        blueTable[i] = ramp[2*256+i] * inv65535;
   11.25 +    }
   11.26 +
   11.27 +    if (CGSetDisplayTransferByTable(display_id, tableSize,
   11.28 +                                    redTable, greenTable, blueTable) != CGDisplayNoErr) {
   11.29 +        SDL_SetError("CGSetDisplayTransferByTable()");
   11.30 +        return -1;
   11.31 +    }
   11.32 +    return 0;
   11.33 +}
   11.34 +
   11.35 +int
   11.36 +Cocoa_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp)
   11.37 +{
   11.38 +    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
   11.39 +    CGDirectDisplayID display_id = ((SDL_DisplayData *)display->driverdata)->display;
   11.40 +    const uint32_t tableSize = 256;
   11.41 +    CGGammaValue redTable[tableSize];
   11.42 +    CGGammaValue greenTable[tableSize];
   11.43 +    CGGammaValue blueTable[tableSize];
   11.44 +    uint32_t i, tableCopied;
   11.45 +
   11.46 +    if (CGGetDisplayTransferByTable(display_id, tableSize,
   11.47 +                                    redTable, greenTable, blueTable, &tableCopied) != CGDisplayNoErr) {
   11.48 +        SDL_SetError("CGGetDisplayTransferByTable()");
   11.49 +        return -1;
   11.50 +    }
   11.51 +
   11.52 +    for (i = 0; i < tableCopied; i++) {
   11.53 +        ramp[0*256+i] = (Uint16)(redTable[i] * 65535.0f);
   11.54 +        ramp[1*256+i] = (Uint16)(greenTable[i] * 65535.0f);
   11.55 +        ramp[2*256+i] = (Uint16)(blueTable[i] * 65535.0f);
   11.56 +    }
   11.57 +    return 0;
   11.58 +}
   11.59 +
   11.60  void
   11.61  Cocoa_SetWindowGrab(_THIS, SDL_Window * window)
   11.62  {
    12.1 --- a/src/video/windows/SDL_windowsvideo.c	Thu Mar 10 01:03:43 2011 -0800
    12.2 +++ b/src/video/windows/SDL_windowsvideo.c	Fri Mar 11 08:49:20 2011 -0800
    12.3 @@ -125,6 +125,8 @@
    12.4      device->MinimizeWindow = WIN_MinimizeWindow;
    12.5      device->RestoreWindow = WIN_RestoreWindow;
    12.6      device->SetWindowFullscreen = WIN_SetWindowFullscreen;
    12.7 +    device->SetWindowGammaRamp = WIN_SetWindowGammaRamp;
    12.8 +    device->GetWindowGammaRamp = WIN_GetWindowGammaRamp;
    12.9      device->SetWindowGrab = WIN_SetWindowGrab;
   12.10      device->DestroyWindow = WIN_DestroyWindow;
   12.11      device->GetWindowWMInfo = WIN_GetWindowWMInfo;
    13.1 --- a/src/video/windows/SDL_windowswindow.c	Thu Mar 10 01:03:43 2011 -0800
    13.2 +++ b/src/video/windows/SDL_windowswindow.c	Fri Mar 11 08:49:20 2011 -0800
    13.3 @@ -571,6 +571,54 @@
    13.4      SetWindowPos(hwnd, top, x, y, w, h, SWP_NOCOPYBITS);
    13.5  }
    13.6  
    13.7 +int
    13.8 +WIN_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp)
    13.9 +{
   13.10 +#ifdef _WIN32_WCE
   13.11 +    SDL_Unsupported();
   13.12 +    return -1;
   13.13 +#else
   13.14 +    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
   13.15 +    SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
   13.16 +    HDC hdc;
   13.17 +    BOOL succeeded = FALSE;
   13.18 +
   13.19 +    hdc = CreateDC(data->DeviceName, NULL, NULL, NULL);
   13.20 +    if (hdc) {
   13.21 +        succeeded = SetDeviceGammaRamp(hdc, (LPVOID)ramp);
   13.22 +        if (!succeeded) {
   13.23 +            WIN_SetError("SetDeviceGammaRamp()");
   13.24 +        }
   13.25 +        DeleteDC(hdc);
   13.26 +    }
   13.27 +    return succeeded ? 0 : -1;
   13.28 +#endif
   13.29 +}
   13.30 +
   13.31 +int
   13.32 +WIN_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp)
   13.33 +{
   13.34 +#ifdef _WIN32_WCE
   13.35 +    SDL_Unsupported();
   13.36 +    return -1;
   13.37 +#else
   13.38 +    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
   13.39 +    SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
   13.40 +    HDC hdc;
   13.41 +    BOOL succeeded = FALSE;
   13.42 +
   13.43 +    hdc = CreateDC(data->DeviceName, NULL, NULL, NULL);
   13.44 +    if (hdc) {
   13.45 +        succeeded = GetDeviceGammaRamp(hdc, (LPVOID)ramp);
   13.46 +        if (!succeeded) {
   13.47 +            WIN_SetError("GetDeviceGammaRamp()");
   13.48 +        }
   13.49 +        DeleteDC(hdc);
   13.50 +    }
   13.51 +    return succeeded ? 0 : -1;
   13.52 +#endif
   13.53 +}
   13.54 +
   13.55  void
   13.56  WIN_SetWindowGrab(_THIS, SDL_Window * window)
   13.57  {
    14.1 --- a/src/video/windows/SDL_windowswindow.h	Thu Mar 10 01:03:43 2011 -0800
    14.2 +++ b/src/video/windows/SDL_windowswindow.h	Fri Mar 11 08:49:20 2011 -0800
    14.3 @@ -59,6 +59,8 @@
    14.4  extern void WIN_MinimizeWindow(_THIS, SDL_Window * window);
    14.5  extern void WIN_RestoreWindow(_THIS, SDL_Window * window);
    14.6  extern void WIN_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
    14.7 +extern int WIN_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp);
    14.8 +extern int WIN_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp);
    14.9  extern void WIN_SetWindowGrab(_THIS, SDL_Window * window);
   14.10  extern void WIN_DestroyWindow(_THIS, SDL_Window * window);
   14.11  extern SDL_bool WIN_GetWindowWMInfo(_THIS, SDL_Window * window,
    15.1 --- a/src/video/x11/SDL_x11modes.c	Thu Mar 10 01:03:43 2011 -0800
    15.2 +++ b/src/video/x11/SDL_x11modes.c	Fri Mar 11 08:49:20 2011 -0800
    15.3 @@ -47,7 +47,9 @@
    15.4      }
    15.5  
    15.6      depth = DefaultDepth(display, screen);
    15.7 -    if (XMatchVisualInfo(display, screen, depth, TrueColor, vinfo) ||
    15.8 +    if ((X11_UseDirectColorVisuals() &&
    15.9 +         XMatchVisualInfo(display, screen, depth, DirectColor, vinfo)) ||
   15.10 +        XMatchVisualInfo(display, screen, depth, TrueColor, vinfo) ||
   15.11          XMatchVisualInfo(display, screen, depth, PseudoColor, vinfo) ||
   15.12          XMatchVisualInfo(display, screen, depth, StaticColor, vinfo)) {
   15.13          return 0;
    16.1 --- a/src/video/x11/SDL_x11video.c	Thu Mar 10 01:03:43 2011 -0800
    16.2 +++ b/src/video/x11/SDL_x11video.c	Fri Mar 11 08:49:20 2011 -0800
    16.3 @@ -202,6 +202,7 @@
    16.4      device->MinimizeWindow = X11_MinimizeWindow;
    16.5      device->RestoreWindow = X11_RestoreWindow;
    16.6      device->SetWindowFullscreen = X11_SetWindowFullscreen;
    16.7 +    device->SetWindowGammaRamp = X11_SetWindowGammaRamp;
    16.8      device->SetWindowGrab = X11_SetWindowGrab;
    16.9      device->DestroyWindow = X11_DestroyWindow;
   16.10      device->CreateWindowFramebuffer = X11_CreateWindowFramebuffer;
   16.11 @@ -383,4 +384,10 @@
   16.12      X11_QuitTouch(_this);
   16.13  }
   16.14  
   16.15 +SDL_bool
   16.16 +X11_UseDirectColorVisuals(void)
   16.17 +{
   16.18 +    return SDL_getenv("SDL_VIDEO_X11_NODIRECTCOLOR") ? SDL_FALSE : SDL_TRUE;
   16.19 +}
   16.20 +
   16.21  /* vim: set ts=4 sw=4 expandtab: */
    17.1 --- a/src/video/x11/SDL_x11video.h	Thu Mar 10 01:03:43 2011 -0800
    17.2 +++ b/src/video/x11/SDL_x11video.h	Fri Mar 11 08:49:20 2011 -0800
    17.3 @@ -92,6 +92,8 @@
    17.4      SDL_bool selection_waiting;
    17.5  } SDL_VideoData;
    17.6  
    17.7 +extern SDL_bool X11_UseDirectColorVisuals(void);
    17.8 +
    17.9  #endif /* _SDL_x11video_h */
   17.10  
   17.11  /* vi: set ts=4 sw=4 expandtab: */
    18.1 --- a/src/video/x11/SDL_x11window.c	Thu Mar 10 01:03:43 2011 -0800
    18.2 +++ b/src/video/x11/SDL_x11window.c	Fri Mar 11 08:49:20 2011 -0800
    18.3 @@ -175,6 +175,7 @@
    18.4              window->flags &= ~SDL_WINDOW_SHOWN;
    18.5          }
    18.6          data->visual = attrib.visual;
    18.7 +        data->colormap = attrib.colormap;
    18.8      }
    18.9  
   18.10      {
   18.11 @@ -316,7 +317,88 @@
   18.12      xattr.override_redirect = False;
   18.13      xattr.background_pixel = 0;
   18.14      xattr.border_pixel = 0;
   18.15 -    xattr.colormap = XCreateColormap(display, RootWindow(display, screen), visual, AllocNone);
   18.16 +
   18.17 +    if (visual->class == DirectColor) {
   18.18 +        Status status;
   18.19 +        XColor *colorcells;
   18.20 +        int i;
   18.21 +        int ncolors;
   18.22 +        int rmax, gmax, bmax;
   18.23 +        int rmask, gmask, bmask;
   18.24 +        int rshift, gshift, bshift;
   18.25 +
   18.26 +        xattr.colormap =
   18.27 +            XCreateColormap(display, RootWindow(display, screen),
   18.28 +                            visual, AllocAll);
   18.29 +
   18.30 +        /* If we can't create a colormap, then we must die */
   18.31 +        if (!xattr.colormap) {
   18.32 +            SDL_SetError("Could not create writable colormap");
   18.33 +            return -1;
   18.34 +        }
   18.35 +
   18.36 +        /* OK, we got a colormap, now fill it in as best as we can */
   18.37 +        colorcells = SDL_malloc(visual->map_entries * sizeof(XColor));
   18.38 +        if (!colorcells) {
   18.39 +            SDL_OutOfMemory();
   18.40 +            return -1;
   18.41 +        }
   18.42 +        ncolors = visual->map_entries;
   18.43 +        rmax = 0xffff;
   18.44 +        gmax = 0xffff;
   18.45 +        bmax = 0xffff;
   18.46 +
   18.47 +        rshift = 0;
   18.48 +        rmask = visual->red_mask;
   18.49 +        while (0 == (rmask & 1)) {
   18.50 +            rshift++;
   18.51 +            rmask >>= 1;
   18.52 +        }
   18.53 +
   18.54 +        gshift = 0;
   18.55 +        gmask = visual->green_mask;
   18.56 +        while (0 == (gmask & 1)) {
   18.57 +            gshift++;
   18.58 +            gmask >>= 1;
   18.59 +        }
   18.60 +
   18.61 +        bshift = 0;
   18.62 +        bmask = visual->blue_mask;
   18.63 +        while (0 == (bmask & 1)) {
   18.64 +            bshift++;
   18.65 +            bmask >>= 1;
   18.66 +        }
   18.67 +
   18.68 +        /* build the color table pixel values */
   18.69 +        for (i = 0; i < ncolors; i++) {
   18.70 +            Uint32 red = (rmax * i) / (ncolors - 1);
   18.71 +            Uint32 green = (gmax * i) / (ncolors - 1);
   18.72 +            Uint32 blue = (bmax * i) / (ncolors - 1);
   18.73 +
   18.74 +            Uint32 rbits = (rmask * i) / (ncolors - 1);
   18.75 +            Uint32 gbits = (gmask * i) / (ncolors - 1);
   18.76 +            Uint32 bbits = (bmask * i) / (ncolors - 1);
   18.77 +
   18.78 +            Uint32 pix =
   18.79 +                (rbits << rshift) | (gbits << gshift) | (bbits << bshift);
   18.80 +
   18.81 +            colorcells[i].pixel = pix;
   18.82 +
   18.83 +            colorcells[i].red = red;
   18.84 +            colorcells[i].green = green;
   18.85 +            colorcells[i].blue = blue;
   18.86 +
   18.87 +            colorcells[i].flags = DoRed | DoGreen | DoBlue;
   18.88 +        }
   18.89 +
   18.90 +        XStoreColors(display, xattr.colormap, colorcells, ncolors);
   18.91 +
   18.92 +        SDL_free(colorcells);
   18.93 +    } else {
   18.94 +        xattr.colormap =
   18.95 +            XCreateColormap(display, RootWindow(display, screen),
   18.96 +                            visual, AllocNone);
   18.97 +    }
   18.98  
   18.99      w = XCreateWindow(display, RootWindow(display, screen),
  18.100                        window->x, window->y, window->w, window->h,
  18.101 @@ -861,6 +943,75 @@
  18.102      XFlush(display);
  18.103  }
  18.104  
  18.105 +int
  18.106 +X11_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp)
  18.107 +{
  18.108 +    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
  18.109 +    Display *display = data->videodata->display;
  18.110 +    Visual *visual = data->visual;
  18.111 +    Colormap colormap = data->colormap;
  18.112 +    XColor *colorcells;
  18.113 +    int ncolors;
  18.114 +    int rmask, gmask, bmask;
  18.115 +    int rshift, gshift, bshift;
  18.116 +    int i, j;
  18.117 +
  18.118 +    if (visual->class != DirectColor) {
  18.119 +        SDL_SetError("Window doesn't have DirectColor visual");
  18.120 +        return -1;
  18.121 +    }
  18.122 +
  18.123 +    ncolors = visual->map_entries;
  18.124 +    colorcells = SDL_malloc(ncolors * sizeof(XColor));
  18.125 +    if (!colorcells) {
  18.126 +        SDL_OutOfMemory();
  18.127 +        return -1;
  18.128 +    }
  18.129 +
  18.130 +    rshift = 0;
  18.131 +    rmask = visual->red_mask;
  18.132 +    while (0 == (rmask & 1)) {
  18.133 +        rshift++;
  18.134 +        rmask >>= 1;
  18.135 +    }
  18.136 +
  18.137 +    gshift = 0;
  18.138 +    gmask = visual->green_mask;
  18.139 +    while (0 == (gmask & 1)) {
  18.140 +        gshift++;
  18.141 +        gmask >>= 1;
  18.142 +    }
  18.143 +
  18.144 +    bshift = 0;
  18.145 +    bmask = visual->blue_mask;
  18.146 +    while (0 == (bmask & 1)) {
  18.147 +        bshift++;
  18.148 +        bmask >>= 1;
  18.149 +    }
  18.150 +
  18.151 +    /* build the color table pixel values */
  18.152 +    for (i = 0; i < ncolors; i++) {
  18.153 +        Uint32 rbits = (rmask * i) / (ncolors - 1);
  18.154 +        Uint32 gbits = (gmask * i) / (ncolors - 1);
  18.155 +        Uint32 bbits = (bmask * i) / (ncolors - 1);
  18.156 +        Uint32 pix = (rbits << rshift) | (gbits << gshift) | (bbits << bshift);
  18.157 +
  18.158 +        colorcells[i].pixel = pix;
  18.159 +
  18.160 +        colorcells[i].red = ramp[(0 * 256) + i];
  18.161 +        colorcells[i].green = ramp[(1 * 256) + i];
  18.162 +        colorcells[i].blue = ramp[(2 * 256) + i];
  18.163 +
  18.164 +        colorcells[i].flags = DoRed | DoGreen | DoBlue;
  18.165 +    }
  18.166 +
  18.167 +    XStoreColors(display, colormap, colorcells, ncolors);
  18.168 +    XFlush(display);
  18.169 +    SDL_free(colorcells);
  18.170 +
  18.171 +    return 0;
  18.172 +}
  18.173 +
  18.174  void
  18.175  X11_SetWindowGrab(_THIS, SDL_Window * window)
  18.176  {
    19.1 --- a/src/video/x11/SDL_x11window.h	Thu Mar 10 01:03:43 2011 -0800
    19.2 +++ b/src/video/x11/SDL_x11window.h	Fri Mar 11 08:49:20 2011 -0800
    19.3 @@ -29,6 +29,7 @@
    19.4      SDL_Window *window;
    19.5      Window xwindow;
    19.6      Visual *visual;
    19.7 +    Colormap colormap;
    19.8  #ifndef NO_SHARED_MEMORY
    19.9      /* MIT shared memory extension information */
   19.10      SDL_bool use_mitshm;
   19.11 @@ -55,6 +56,7 @@
   19.12  extern void X11_MinimizeWindow(_THIS, SDL_Window * window);
   19.13  extern void X11_RestoreWindow(_THIS, SDL_Window * window);
   19.14  extern void X11_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
   19.15 +extern int X11_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp);
   19.16  extern void X11_SetWindowGrab(_THIS, SDL_Window * window);
   19.17  extern void X11_DestroyWindow(_THIS, SDL_Window * window);
   19.18  extern SDL_bool X11_GetWindowWMInfo(_THIS, SDL_Window * window,
    20.1 --- a/test/Makefile.in	Thu Mar 10 01:03:43 2011 -0800
    20.2 +++ b/test/Makefile.in	Fri Mar 11 08:49:20 2011 -0800
    20.3 @@ -23,6 +23,7 @@
    20.4  	testerror$(EXE) \
    20.5  	testfile$(EXE) \
    20.6  	testfill$(EXE) \
    20.7 +	testgamma$(EXE) \
    20.8  	testgesture$(EXE) \
    20.9  	testgl$(EXE) \
   20.10  	testgl2$(EXE) \
   20.11 @@ -119,6 +120,9 @@
   20.12  testfill$(EXE): $(srcdir)/testfill.c
   20.13  	$(CC) -o $@ $? $(CFLAGS) $(LIBS)
   20.14  
   20.15 +testgamma$(EXE): $(srcdir)/testgamma.c
   20.16 +	$(CC) -o $@ $? $(CFLAGS) $(LIBS)
   20.17 + 
   20.18  testgesture$(EXE): $(srcdir)/testgesture.c
   20.19  	$(CC) -o $@ $? $(CFLAGS) $(LIBS) @MATHLIB@
   20.20   
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/test/testgamma.c	Fri Mar 11 08:49:20 2011 -0800
    21.3 @@ -0,0 +1,168 @@
    21.4 +
    21.5 +/* Bring up a window and manipulate the gamma on it */
    21.6 +
    21.7 +#include <stdlib.h>
    21.8 +#include <stdio.h>
    21.9 +#include <string.h>
   21.10 +#include <math.h>
   21.11 +
   21.12 +#include "SDL.h"
   21.13 +
   21.14 +/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
   21.15 +static void
   21.16 +quit(int rc)
   21.17 +{
   21.18 +    SDL_Quit();
   21.19 +    exit(rc);
   21.20 +}
   21.21 +
   21.22 +/* This can be used as a general routine for all of the test programs */
   21.23 +int
   21.24 +get_video_args(char *argv[], int *w, int *h, int *bpp, Uint32 * flags)
   21.25 +{
   21.26 +    int i;
   21.27 +
   21.28 +    *w = 640;
   21.29 +    *h = 480;
   21.30 +    *bpp = 0;
   21.31 +    *flags = SDL_SWSURFACE;
   21.32 +
   21.33 +    for (i = 1; argv[i]; ++i) {
   21.34 +        if (strcmp(argv[i], "-width") == 0) {
   21.35 +            if (argv[i + 1]) {
   21.36 +                *w = atoi(argv[++i]);
   21.37 +            }
   21.38 +        } else if (strcmp(argv[i], "-height") == 0) {
   21.39 +            if (argv[i + 1]) {
   21.40 +                *h = atoi(argv[++i]);
   21.41 +            }
   21.42 +        } else if (strcmp(argv[i], "-bpp") == 0) {
   21.43 +            if (argv[i + 1]) {
   21.44 +                *bpp = atoi(argv[++i]);
   21.45 +            }
   21.46 +        } else if (strcmp(argv[i], "-fullscreen") == 0) {
   21.47 +            *flags |= SDL_FULLSCREEN;
   21.48 +        } else if (strcmp(argv[i], "-hw") == 0) {
   21.49 +            *flags |= SDL_HWSURFACE;
   21.50 +        } else if (strcmp(argv[i], "-hwpalette") == 0) {
   21.51 +            *flags |= SDL_HWPALETTE;
   21.52 +        } else
   21.53 +            break;
   21.54 +    }
   21.55 +    return i;
   21.56 +}
   21.57 +
   21.58 +int
   21.59 +main(int argc, char *argv[])
   21.60 +{
   21.61 +    SDL_Surface *screen;
   21.62 +    SDL_Surface *image;
   21.63 +    float gamma;
   21.64 +    int i;
   21.65 +    int w, h, bpp;
   21.66 +    Uint32 flags;
   21.67 +    Uint16 ramp[256];
   21.68 +    Uint16 red_ramp[256];
   21.69 +    Uint32 then, timeout;
   21.70 +
   21.71 +    /* Check command line arguments */
   21.72 +    argv += get_video_args(argv, &w, &h, &bpp, &flags);
   21.73 +
   21.74 +    /* Initialize SDL */
   21.75 +    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
   21.76 +        fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
   21.77 +        return (1);
   21.78 +    }
   21.79 +
   21.80 +    /* Initialize the display, always use hardware palette */
   21.81 +    screen = SDL_SetVideoMode(w, h, bpp, flags | SDL_HWPALETTE);
   21.82 +    if (screen == NULL) {
   21.83 +        fprintf(stderr, "Couldn't set %dx%d video mode: %s\n",
   21.84 +                w, h, SDL_GetError());
   21.85 +        quit(1);
   21.86 +    }
   21.87 +
   21.88 +    /* Set the window manager title bar */
   21.89 +    SDL_WM_SetCaption("SDL gamma test", "testgamma");
   21.90 +
   21.91 +    /* Set the desired gamma, if any */
   21.92 +    gamma = 1.0f;
   21.93 +    if (*argv) {
   21.94 +        gamma = (float) atof(*argv);
   21.95 +    }
   21.96 +    if (SDL_SetGamma(gamma, gamma, gamma) < 0) {
   21.97 +        fprintf(stderr, "Unable to set gamma: %s\n", SDL_GetError());
   21.98 +        quit(1);
   21.99 +    }
  21.100 +
  21.101 +    /* Do all the drawing work */
  21.102 +    image = SDL_LoadBMP("sample.bmp");
  21.103 +    if (image) {
  21.104 +        SDL_Rect dst;
  21.105 +
  21.106 +        dst.x = (screen->w - image->w) / 2;
  21.107 +        dst.y = (screen->h - image->h) / 2;
  21.108 +        dst.w = image->w;
  21.109 +        dst.h = image->h;
  21.110 +        SDL_BlitSurface(image, NULL, screen, &dst);
  21.111 +        SDL_UpdateRects(screen, 1, &dst);
  21.112 +    }
  21.113 +
  21.114 +    /* Wait a bit, handling events */
  21.115 +    then = SDL_GetTicks();
  21.116 +    timeout = (5 * 1000);
  21.117 +    while ((SDL_GetTicks() - then) < timeout) {
  21.118 +        SDL_Event event;
  21.119 +
  21.120 +        while (SDL_PollEvent(&event)) {
  21.121 +            switch (event.type) {
  21.122 +            case SDL_QUIT:     /* Quit now */
  21.123 +                timeout = 0;
  21.124 +                break;
  21.125 +            case SDL_KEYDOWN:
  21.126 +                switch (event.key.keysym.sym) {
  21.127 +                case SDLK_SPACE:       /* Go longer.. */
  21.128 +                    timeout += (5 * 1000);
  21.129 +                    break;
  21.130 +                case SDLK_UP:
  21.131 +                    gamma += 0.2f;
  21.132 +                    SDL_SetGamma(gamma, gamma, gamma);
  21.133 +                    break;
  21.134 +                case SDLK_DOWN:
  21.135 +                    gamma -= 0.2f;
  21.136 +                    SDL_SetGamma(gamma, gamma, gamma);
  21.137 +                    break;
  21.138 +                case SDLK_ESCAPE:
  21.139 +                    timeout = 0;
  21.140 +                    break;
  21.141 +                default:
  21.142 +                    break;
  21.143 +                }
  21.144 +                break;
  21.145 +            }
  21.146 +        }
  21.147 +    }
  21.148 +
  21.149 +    /* Perform a gamma flash to red using color ramps */
  21.150 +    while (gamma < 10.0) {
  21.151 +        /* Increase the red gamma and decrease everything else... */
  21.152 +        gamma += 0.1f;
  21.153 +        SDL_CalculateGammaRamp(gamma, red_ramp);
  21.154 +        SDL_CalculateGammaRamp(1.0f / gamma, ramp);
  21.155 +        SDL_SetGammaRamp(red_ramp, ramp, ramp);
  21.156 +    }
  21.157 +    /* Finish completely red */
  21.158 +    memset(red_ramp, 255, sizeof(red_ramp));
  21.159 +    memset(ramp, 0, sizeof(ramp));
  21.160 +    SDL_SetGammaRamp(red_ramp, ramp, ramp);
  21.161 +
  21.162 +    /* Now fade out to black */
  21.163 +    for (i = (red_ramp[0] >> 8); i >= 0; --i) {
  21.164 +        memset(red_ramp, i, sizeof(red_ramp));
  21.165 +        SDL_SetGammaRamp(red_ramp, NULL, NULL);
  21.166 +    }
  21.167 +    SDL_Delay(1 * 1000);
  21.168 +
  21.169 +    SDL_Quit();
  21.170 +    return (0);
  21.171 +}