Subversion Repositories Kolibri OS

Rev

Rev 8210 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
8210 maxcodehac 1
/*
2
    SDL - Simple DirectMedia Layer
3
    Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
4
 
5
    This library is free software; you can redistribute it and/or
6
    modify it under the terms of the GNU Library General Public
7
    License as published by the Free Software Foundation; either
8
    version 2 of the License, or (at your option) any later version.
9
 
10
    This library is distributed in the hope that it will be useful,
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
    Library General Public License for more details.
14
 
15
    You should have received a copy of the GNU Library General Public
16
    License along with this library; if not, write to the Free
17
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 
19
    Sam Lantinga
20
    slouken@devolution.com
21
*/
22
 
23
 
24
/* Gamma correction support */
25
 
26
#define USE_MATH_H	/* Used for calculating gamma ramps */
27
 
28
#ifdef USE_MATH_H
29
#include 
30
#endif
31
#include 
8214 maxcodehac 32
#include 
8210 maxcodehac 33
 
34
#include "SDL_error.h"
35
#include "SDL_sysvideo.h"
36
 
37
#ifdef USE_MATH_H
38
static void CalculateGammaRamp(float gamma, Uint16 *ramp)
39
{
40
	int i;
41
 
42
	/* 0.0 gamma is all black */
43
	if ( gamma <= 0.0 ) {
44
		for ( i=0; i<256; ++i ) {
45
			ramp[i] = 0;
46
		}
47
		return;
48
	} else
49
	/* 1.0 gamma is identity */
50
	if ( gamma == 1.0 ) {
51
		for ( i=0; i<256; ++i ) {
52
			ramp[i] = (i << 8) | i;
53
		}
54
		return;
55
	} else
56
	/* Calculate a real gamma ramp */
57
	{ int value;
58
		gamma = 1.0f / gamma;
59
		for ( i=0; i<256; ++i ) {
60
			value = (int)(pow((double)i/256.0, gamma)*65535.0+0.5);
61
			if ( value > 65535 ) {
62
				value = 65535;
63
			}
64
			ramp[i] = (Uint16)value;
65
		}
66
	}
67
}
68
static void CalculateGammaFromRamp(float *gamma, Uint16 *ramp)
69
{
70
	/* The following is adapted from a post by Garrett Bass on OpenGL
71
	   Gamedev list, March 4, 2000.
72
	 */
73
	float sum = 0.0;
74
	int i, count = 0;
75
 
76
	*gamma = 1.0;
77
	for ( i = 1; i < 256; ++i ) {
78
	    if ( (ramp[i] != 0) && (ramp[i] != 65535) ) {
79
	        double B = (double)i / 256.0;
80
	        double A = ramp[i] / 65535.0;
81
	        sum += (float) ( log(A) / log(B) );
82
	        count++;
83
	    }
84
	}
85
	if ( count && sum ) {
86
		*gamma = 1.0f / (sum / count);
87
	}
88
}
89
#endif /* USE_MATH_H */
90
 
91
int SDL_SetGamma(float red, float green, float blue)
92
{
93
	int succeeded;
94
	SDL_VideoDevice *video = current_video;
95
	SDL_VideoDevice *this  = current_video;
96
 
97
	succeeded = -1;
98
#ifdef USE_MATH_H
99
	/* Prefer using SetGammaRamp(), as it's more flexible */
100
	{
101
		Uint16 ramp[3][256];
102
 
103
		CalculateGammaRamp(red, ramp[0]);
104
		CalculateGammaRamp(green, ramp[1]);
105
		CalculateGammaRamp(blue, ramp[2]);
106
		succeeded = SDL_SetGammaRamp(ramp[0], ramp[1], ramp[2]);
107
	}
108
#else
109
	SDL_SetError("Gamma correction not supported");
110
#endif
111
	if ( (succeeded < 0) && video->SetGamma ) {
112
		SDL_ClearError();
113
		succeeded = video->SetGamma(this, red, green, blue);
114
	}
115
	return succeeded;
116
}
117
 
118
/* Calculating the gamma by integrating the gamma ramps isn't exact,
119
   so this function isn't officially supported.
120
*/
121
int SDL_GetGamma(float *red, float *green, float *blue)
122
{
123
	int succeeded;
124
	SDL_VideoDevice *video = current_video;
125
	SDL_VideoDevice *this  = current_video;
126
 
127
	succeeded = -1;
128
#ifdef USE_MATH_H
129
	/* Prefer using GetGammaRamp(), as it's more flexible */
130
	{
131
		Uint16 ramp[3][256];
132
 
133
		succeeded = SDL_GetGammaRamp(ramp[0], ramp[1], ramp[2]);
134
		if ( succeeded >= 0 ) {
135
			CalculateGammaFromRamp(red, ramp[0]);
136
			CalculateGammaFromRamp(green, ramp[1]);
137
			CalculateGammaFromRamp(blue, ramp[2]);
138
		}
139
	}
140
#else
141
	SDL_SetError("Gamma correction not supported");
142
#endif
143
	if ( (succeeded < 0) && video->GetGamma ) {
144
		SDL_ClearError();
145
		succeeded = video->GetGamma(this, red, green, blue);
146
	}
147
	return succeeded;
148
}
149
 
150
int SDL_SetGammaRamp(Uint16 *red, Uint16 *green, Uint16 *blue)
151
{
152
	int succeeded;
153
	SDL_VideoDevice *video = current_video;
154
	SDL_VideoDevice *this  = current_video;
155
	SDL_Surface *screen = SDL_PublicSurface;
156
 
157
	/* Verify the screen parameter */
158
	if ( !screen ) {
159
		SDL_SetError("No video mode has been set");
160
		return -1;
161
	}
162
 
163
	/* Lazily allocate the gamma tables */
164
	if ( ! video->gamma ) {
165
		SDL_GetGammaRamp(0, 0, 0);
166
	}
167
 
168
	/* Fill the gamma table with the new values */
169
	if ( red ) {
170
		memcpy(&video->gamma[0*256], red, 256*sizeof(*video->gamma));
171
	}
172
	if ( green ) {
173
		memcpy(&video->gamma[1*256], green, 256*sizeof(*video->gamma));
174
	}
175
	if ( blue ) {
176
		memcpy(&video->gamma[2*256], blue, 256*sizeof(*video->gamma));
177
	}
178
 
179
	/* Gamma correction always possible on split palettes */
180
	if ( (screen->flags & SDL_HWPALETTE) == SDL_HWPALETTE ) {
181
		SDL_Palette *pal = screen->format->palette;
182
 
183
		/* If physical palette has been set independently, use it */
184
		if(video->physpal)
185
		        pal = video->physpal;
186
 
187
		SDL_SetPalette(screen, SDL_PHYSPAL,
188
			       pal->colors, 0, pal->ncolors);
189
		return 0;
190
	}
191
 
192
	/* Try to set the gamma ramp in the driver */
193
	succeeded = -1;
194
	if ( video->SetGammaRamp ) {
195
		succeeded = video->SetGammaRamp(this, video->gamma);
196
	} else {
197
		SDL_SetError("Gamma ramp manipulation not supported");
198
	}
199
	return succeeded;
200
}
201
 
202
int SDL_GetGammaRamp(Uint16 *red, Uint16 *green, Uint16 *blue)
203
{
204
	SDL_VideoDevice *video = current_video;
205
	SDL_VideoDevice *this  = current_video;
206
 
207
	/* Lazily allocate the gamma table */
208
	if ( ! video->gamma ) {
209
		video->gamma = malloc(3*256*sizeof(*video->gamma));
210
		if ( ! video->gamma ) {
211
			SDL_OutOfMemory();
212
			return -1;
213
		}
214
		if ( video->GetGammaRamp ) {
215
			/* Get the real hardware gamma */
216
			video->GetGammaRamp(this, video->gamma);
217
		} else {
218
			/* Assume an identity gamma */
219
			int i;
220
			for ( i=0; i<256; ++i ) {
221
				video->gamma[0*256+i] = (i << 8) | i;
222
				video->gamma[1*256+i] = (i << 8) | i;
223
				video->gamma[2*256+i] = (i << 8) | i;
224
			}
225
		}
226
	}
227
 
228
	/* Just copy from our internal table */
229
	if ( red ) {
230
		memcpy(red, &video->gamma[0*256], 256*sizeof(*red));
231
	}
232
	if ( green ) {
233
		memcpy(green, &video->gamma[1*256], 256*sizeof(*green));
234
	}
235
	if ( blue ) {
236
		memcpy(blue, &video->gamma[2*256], 256*sizeof(*blue));
237
	}
238
	return 0;
239
}