comparison src/video/SDL_gamma.c @ 1662:782fd950bd46 SDL-1.3

Revamp of the video system in progress - adding support for multiple displays, multiple windows, and a full video mode selection API. WARNING: None of the video drivers have been updated for the new API yet! The API is still under design and very fluid. The code is now run through a consistent indent format: indent -i4 -nut -nsc -br -ce The headers are being converted to automatically generate doxygen documentation.
author Sam Lantinga <slouken@libsdl.org>
date Sun, 28 May 2006 13:04:16 +0000
parents 97d0966f4bf7
children 4da1ee79c9af
comparison
equal deleted inserted replaced
1661:281d3f4870e5 1662:782fd950bd46
22 #include "SDL_config.h" 22 #include "SDL_config.h"
23 23
24 /* Gamma correction support */ 24 /* Gamma correction support */
25 25
26 #ifdef HAVE_MATH_H 26 #ifdef HAVE_MATH_H
27 #include <math.h> /* Used for calculating gamma ramps */ 27 #include <math.h> /* Used for calculating gamma ramps */
28 #else 28 #else
29 /* Math routines from uClibc: http://www.uclibc.org */ 29 /* Math routines from uClibc: http://www.uclibc.org */
30 #include "math_private.h" 30 #include "math_private.h"
31 #include "e_sqrt.h" 31 #include "e_sqrt.h"
32 #include "e_pow.h" 32 #include "e_pow.h"
36 #endif 36 #endif
37 37
38 #include "SDL_sysvideo.h" 38 #include "SDL_sysvideo.h"
39 39
40 40
41 static void CalculateGammaRamp(float gamma, Uint16 *ramp) 41 static void
42 { 42 CalculateGammaRamp (float gamma, Uint16 * ramp)
43 int i; 43 {
44 44 int i;
45 /* 0.0 gamma is all black */ 45
46 if ( gamma <= 0.0f ) { 46 /* 0.0 gamma is all black */
47 for ( i=0; i<256; ++i ) { 47 if (gamma <= 0.0f) {
48 ramp[i] = 0; 48 for (i = 0; i < 256; ++i) {
49 } 49 ramp[i] = 0;
50 return; 50 }
51 } else 51 return;
52 /* 1.0 gamma is identity */ 52 } else
53 if ( gamma >= 1.0f ) { 53 /* 1.0 gamma is identity */
54 for ( i=0; i<256; ++i ) { 54 if (gamma >= 1.0f) {
55 ramp[i] = (i << 8) | i; 55 for (i = 0; i < 256; ++i) {
56 } 56 ramp[i] = (i << 8) | i;
57 return; 57 }
58 } else 58 return;
59 /* Calculate a real gamma ramp */ 59 } else
60 { int value; 60 /* Calculate a real gamma ramp */
61 gamma = 1.0f / gamma; 61 {
62 for ( i=0; i<256; ++i ) { 62 int value;
63 value = (int)(pow((double)i/256.0, gamma)*65535.0+0.5); 63 gamma = 1.0f / gamma;
64 if ( value > 65535 ) { 64 for (i = 0; i < 256; ++i) {
65 value = 65535; 65 value = (int) (pow ((double) i / 256.0, gamma) * 65535.0 + 0.5);
66 } 66 if (value > 65535) {
67 ramp[i] = (Uint16)value; 67 value = 65535;
68 } 68 }
69 } 69 ramp[i] = (Uint16) value;
70 } 70 }
71 static void CalculateGammaFromRamp(float *gamma, Uint16 *ramp) 71 }
72 { 72 }
73 /* The following is adapted from a post by Garrett Bass on OpenGL 73 static void
74 Gamedev list, March 4, 2000. 74 CalculateGammaFromRamp (float *gamma, Uint16 * ramp)
75 */ 75 {
76 float sum = 0.0f; 76 /* The following is adapted from a post by Garrett Bass on OpenGL
77 int i, count = 0; 77 Gamedev list, March 4, 2000.
78 78 */
79 *gamma = 1.0; 79 float sum = 0.0f;
80 for ( i = 1; i < 256; ++i ) { 80 int i, count = 0;
81 if ( (ramp[i] != 0) && (ramp[i] != 65535) ) { 81
82 double B = (double)i / 256.0; 82 *gamma = 1.0;
83 double A = ramp[i] / 65535.0; 83 for (i = 1; i < 256; ++i) {
84 sum += (float) ( log(A) / log(B) ); 84 if ((ramp[i] != 0) && (ramp[i] != 65535)) {
85 count++; 85 double B = (double) i / 256.0;
86 } 86 double A = ramp[i] / 65535.0;
87 } 87 sum += (float) (log (A) / log (B));
88 if ( count && sum > 0.0f ) { 88 count++;
89 *gamma = 1.0f / (sum / count); 89 }
90 } 90 }
91 } 91 if (count && sum > 0.0f) {
92 92 *gamma = 1.0f / (sum / count);
93 int SDL_SetGamma(float red, float green, float blue) 93 }
94 { 94 }
95 int succeeded; 95
96 SDL_VideoDevice *video = current_video; 96 int
97 SDL_VideoDevice *this = current_video; 97 SDL_SetGamma (float red, float green, float blue)
98 98 {
99 succeeded = -1; 99 SDL_VideoDevice *_this = SDL_GetVideoDevice ();
100 /* Prefer using SetGammaRamp(), as it's more flexible */ 100 int succeeded;
101 { 101
102 Uint16 ramp[3][256]; 102 succeeded = -1;
103 103 /* Prefer using SetGammaRamp(), as it's more flexible */
104 CalculateGammaRamp(red, ramp[0]); 104 {
105 CalculateGammaRamp(green, ramp[1]); 105 Uint16 ramp[3][256];
106 CalculateGammaRamp(blue, ramp[2]); 106
107 succeeded = SDL_SetGammaRamp(ramp[0], ramp[1], ramp[2]); 107 CalculateGammaRamp (red, ramp[0]);
108 } 108 CalculateGammaRamp (green, ramp[1]);
109 if ( (succeeded < 0) && video->SetGamma ) { 109 CalculateGammaRamp (blue, ramp[2]);
110 SDL_ClearError(); 110 succeeded = SDL_SetGammaRamp (ramp[0], ramp[1], ramp[2]);
111 succeeded = video->SetGamma(this, red, green, blue); 111 }
112 } 112 if ((succeeded < 0) && _this->SetGamma) {
113 return succeeded; 113 SDL_ClearError ();
114 succeeded = _this->SetGamma (_this, red, green, blue);
115 }
116 return succeeded;
114 } 117 }
115 118
116 /* Calculating the gamma by integrating the gamma ramps isn't exact, 119 /* Calculating the gamma by integrating the gamma ramps isn't exact,
117 so this function isn't officially supported. 120 so this function isn't officially supported.
118 */ 121 */
119 int SDL_GetGamma(float *red, float *green, float *blue) 122 int
120 { 123 SDL_GetGamma (float *red, float *green, float *blue)
121 int succeeded; 124 {
122 SDL_VideoDevice *video = current_video; 125 SDL_VideoDevice *_this = SDL_GetVideoDevice ();
123 SDL_VideoDevice *this = current_video; 126 int succeeded;
124 127
125 succeeded = -1; 128 succeeded = -1;
126 /* Prefer using GetGammaRamp(), as it's more flexible */ 129 /* Prefer using GetGammaRamp(), as it's more flexible */
127 { 130 {
128 Uint16 ramp[3][256]; 131 Uint16 ramp[3][256];
129 132
130 succeeded = SDL_GetGammaRamp(ramp[0], ramp[1], ramp[2]); 133 succeeded = SDL_GetGammaRamp (ramp[0], ramp[1], ramp[2]);
131 if ( succeeded >= 0 ) { 134 if (succeeded >= 0) {
132 CalculateGammaFromRamp(red, ramp[0]); 135 CalculateGammaFromRamp (red, ramp[0]);
133 CalculateGammaFromRamp(green, ramp[1]); 136 CalculateGammaFromRamp (green, ramp[1]);
134 CalculateGammaFromRamp(blue, ramp[2]); 137 CalculateGammaFromRamp (blue, ramp[2]);
135 } 138 }
136 } 139 }
137 if ( (succeeded < 0) && video->GetGamma ) { 140 if ((succeeded < 0) && _this->GetGamma) {
138 SDL_ClearError(); 141 SDL_ClearError ();
139 succeeded = video->GetGamma(this, red, green, blue); 142 succeeded = _this->GetGamma (_this, red, green, blue);
140 } 143 }
141 return succeeded; 144 return succeeded;
142 } 145 }
143 146
144 int SDL_SetGammaRamp(const Uint16 *red, const Uint16 *green, const Uint16 *blue) 147 int
145 { 148 SDL_SetGammaRamp (const Uint16 * red, const Uint16 * green,
146 int succeeded; 149 const Uint16 * blue)
147 SDL_VideoDevice *video = current_video; 150 {
148 SDL_VideoDevice *this = current_video; 151 SDL_VideoDevice *_this = SDL_GetVideoDevice ();
149 SDL_Surface *screen = SDL_PublicSurface; 152 int succeeded;
150 153 SDL_Surface *screen = SDL_PublicSurface;
151 /* Verify the screen parameter */ 154
152 if ( !screen ) { 155 /* Verify the screen parameter */
153 SDL_SetError("No video mode has been set"); 156 if (!screen) {
154 return -1; 157 SDL_SetError ("No video mode has been set");
155 } 158 return -1;
156 159 }
157 /* Lazily allocate the gamma tables */ 160
158 if ( ! video->gamma ) { 161 /* Lazily allocate the gamma tables */
159 SDL_GetGammaRamp(0, 0, 0); 162 if (!SDL_CurrentWindow.gamma) {
160 } 163 SDL_GetGammaRamp (0, 0, 0);
161 164 }
162 /* Fill the gamma table with the new values */ 165
163 if ( red ) { 166 /* Fill the gamma table with the new values */
164 SDL_memcpy(&video->gamma[0*256], red, 256*sizeof(*video->gamma)); 167 if (red) {
165 } 168 SDL_memcpy (&SDL_CurrentWindow.gamma[0 * 256], red,
166 if ( green ) { 169 256 * sizeof (*SDL_CurrentWindow.gamma));
167 SDL_memcpy(&video->gamma[1*256], green, 256*sizeof(*video->gamma)); 170 }
168 } 171 if (green) {
169 if ( blue ) { 172 SDL_memcpy (&SDL_CurrentWindow.gamma[1 * 256], green,
170 SDL_memcpy(&video->gamma[2*256], blue, 256*sizeof(*video->gamma)); 173 256 * sizeof (*SDL_CurrentWindow.gamma));
171 } 174 }
172 175 if (blue) {
173 /* Gamma correction always possible on split palettes */ 176 SDL_memcpy (&SDL_CurrentWindow.gamma[2 * 256], blue,
174 if ( (screen->flags & SDL_HWPALETTE) == SDL_HWPALETTE ) { 177 256 * sizeof (*SDL_CurrentWindow.gamma));
175 SDL_Palette *pal = screen->format->palette; 178 }
176 179
177 /* If physical palette has been set independently, use it */ 180 /* Try to set the gamma ramp in the driver */
178 if(video->physpal) 181 succeeded = -1;
179 pal = video->physpal; 182 if (_this->SetGammaRamp) {
180 183 succeeded = _this->SetGammaRamp (_this, SDL_CurrentWindow.gamma);
181 SDL_SetPalette(screen, SDL_PHYSPAL, 184 } else {
182 pal->colors, 0, pal->ncolors); 185 SDL_SetError ("Gamma ramp manipulation not supported");
183 return 0; 186 }
184 } 187 return succeeded;
185 188 }
186 /* Try to set the gamma ramp in the driver */ 189
187 succeeded = -1; 190 int
188 if ( video->SetGammaRamp ) { 191 SDL_GetGammaRamp (Uint16 * red, Uint16 * green, Uint16 * blue)
189 succeeded = video->SetGammaRamp(this, video->gamma); 192 {
190 } else { 193 SDL_VideoDevice *_this = SDL_GetVideoDevice ();
191 SDL_SetError("Gamma ramp manipulation not supported"); 194
192 } 195 /* Lazily allocate the gamma table */
193 return succeeded; 196 if (!SDL_CurrentWindow.gamma) {
194 } 197 SDL_CurrentWindow.gamma =
195 198 SDL_malloc (3 * 256 * sizeof (*SDL_CurrentWindow.gamma));
196 int SDL_GetGammaRamp(Uint16 *red, Uint16 *green, Uint16 *blue) 199 if (!SDL_CurrentWindow.gamma) {
197 { 200 SDL_OutOfMemory ();
198 SDL_VideoDevice *video = current_video; 201 return -1;
199 SDL_VideoDevice *this = current_video; 202 }
200 203 if (_this->GetGammaRamp) {
201 /* Lazily allocate the gamma table */ 204 /* Get the real hardware gamma */
202 if ( ! video->gamma ) { 205 _this->GetGammaRamp (_this, SDL_CurrentWindow.gamma);
203 video->gamma = SDL_malloc(3*256*sizeof(*video->gamma)); 206 } else {
204 if ( ! video->gamma ) { 207 /* Assume an identity gamma */
205 SDL_OutOfMemory(); 208 int i;
206 return -1; 209 for (i = 0; i < 256; ++i) {
207 } 210 SDL_CurrentWindow.gamma[0 * 256 + i] = (i << 8) | i;
208 if ( video->GetGammaRamp ) { 211 SDL_CurrentWindow.gamma[1 * 256 + i] = (i << 8) | i;
209 /* Get the real hardware gamma */ 212 SDL_CurrentWindow.gamma[2 * 256 + i] = (i << 8) | i;
210 video->GetGammaRamp(this, video->gamma); 213 }
211 } else { 214 }
212 /* Assume an identity gamma */ 215 }
213 int i; 216
214 for ( i=0; i<256; ++i ) { 217 /* Just copy from our internal table */
215 video->gamma[0*256+i] = (i << 8) | i; 218 if (red) {
216 video->gamma[1*256+i] = (i << 8) | i; 219 SDL_memcpy (red, &SDL_CurrentWindow.gamma[0 * 256],
217 video->gamma[2*256+i] = (i << 8) | i; 220 256 * sizeof (*red));
218 } 221 }
219 } 222 if (green) {
220 } 223 SDL_memcpy (green, &SDL_CurrentWindow.gamma[1 * 256],
221 224 256 * sizeof (*green));
222 /* Just copy from our internal table */ 225 }
223 if ( red ) { 226 if (blue) {
224 SDL_memcpy(red, &video->gamma[0*256], 256*sizeof(*red)); 227 SDL_memcpy (blue, &SDL_CurrentWindow.gamma[2 * 256],
225 } 228 256 * sizeof (*blue));
226 if ( green ) { 229 }
227 SDL_memcpy(green, &video->gamma[1*256], 256*sizeof(*green)); 230 return 0;
228 } 231 }
229 if ( blue ) { 232
230 SDL_memcpy(blue, &video->gamma[2*256], 256*sizeof(*blue)); 233 /* vi: set ts=4 sw=4 expandtab: */
231 }
232 return 0;
233 }