This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
SDL_gamma.c
226 lines (201 loc) · 6.3 KB
1
2
/*
SDL - Simple DirectMedia Layer
3
Copyright (C) 1997-2006 Sam Lantinga
4
5
This library is free software; you can redistribute it and/or
6
modify it under the terms of the GNU Lesser General Public
7
License as published by the Free Software Foundation; either
8
version 2.1 of the License, or (at your option) any later version.
9
10
11
12
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
Lesser General Public License for more details.
14
15
16
17
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19
Sam Lantinga
20
slouken@libsdl.org
21
*/
22
#include "SDL_config.h"
23
24
25
/* Gamma correction support */
26
#ifdef HAVE_MATH_H
27
#include <math.h> /* Used for calculating gamma ramps */
28
29
#else
/* Math routines from uClibc: http://www.uclibc.org */
30
31
32
33
34
35
36
37
#include "math_private.h"
#include "e_sqrt.h"
#include "e_pow.h"
#include "e_log.h"
#define pow(x, y) __ieee754_pow(x, y)
#define log(x) __ieee754_log(x)
#endif
38
39
40
#include "SDL_sysvideo.h"
41
static void
42
CalculateGammaRamp(float gamma, Uint16 * ramp)
43
{
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
int i;
/* 0.0 gamma is all black */
if (gamma <= 0.0f) {
for (i = 0; i < 256; ++i) {
ramp[i] = 0;
}
return;
} else
/* 1.0 gamma is identity */
if (gamma >= 1.0f) {
for (i = 0; i < 256; ++i) {
ramp[i] = (i << 8) | i;
}
return;
} else
/* Calculate a real gamma ramp */
{
int value;
gamma = 1.0f / gamma;
for (i = 0; i < 256; ++i) {
65
value = (int) (pow((double) i / 256.0, gamma) * 65535.0 + 0.5);
66
67
68
69
70
71
if (value > 65535) {
value = 65535;
}
ramp[i] = (Uint16) value;
}
}
72
}
73
static void
74
CalculateGammaFromRamp(float *gamma, Uint16 * ramp)
75
{
76
77
78
79
80
81
82
83
84
85
86
/* The following is adapted from a post by Garrett Bass on OpenGL
Gamedev list, March 4, 2000.
*/
float sum = 0.0f;
int i, count = 0;
*gamma = 1.0;
for (i = 1; i < 256; ++i) {
if ((ramp[i] != 0) && (ramp[i] != 65535)) {
double B = (double) i / 256.0;
double A = ramp[i] / 65535.0;
87
sum += (float) (log(A) / log(B));
88
89
90
91
92
93
count++;
}
}
if (count && sum > 0.0f) {
*gamma = 1.0f / (sum / count);
}
94
95
}
96
int
97
SDL_SetGamma(float red, float green, float blue)
98
{
99
SDL_VideoDevice *_this = SDL_GetVideoDevice();
100
101
102
103
104
105
106
int succeeded;
succeeded = -1;
/* Prefer using SetGammaRamp(), as it's more flexible */
{
Uint16 ramp[3][256];
107
108
109
110
CalculateGammaRamp(red, ramp[0]);
CalculateGammaRamp(green, ramp[1]);
CalculateGammaRamp(blue, ramp[2]);
succeeded = SDL_SetGammaRamp(ramp[0], ramp[1], ramp[2]);
111
}
112
if ((succeeded < 0) && _this && _this->SetGamma) {
113
114
SDL_ClearError();
succeeded = _this->SetGamma(_this, red, green, blue);
115
116
}
return succeeded;
117
118
119
120
121
}
/* Calculating the gamma by integrating the gamma ramps isn't exact,
so this function isn't officially supported.
*/
122
int
123
SDL_GetGamma(float *red, float *green, float *blue)
124
{
125
SDL_VideoDevice *_this = SDL_GetVideoDevice();
126
127
128
129
130
131
132
int succeeded;
succeeded = -1;
/* Prefer using GetGammaRamp(), as it's more flexible */
{
Uint16 ramp[3][256];
133
succeeded = SDL_GetGammaRamp(ramp[0], ramp[1], ramp[2]);
134
if (succeeded >= 0) {
135
136
137
CalculateGammaFromRamp(red, ramp[0]);
CalculateGammaFromRamp(green, ramp[1]);
CalculateGammaFromRamp(blue, ramp[2]);
138
139
}
}
140
if ((succeeded < 0) && _this && _this->GetGamma) {
141
142
SDL_ClearError();
succeeded = _this->GetGamma(_this, red, green, blue);
143
144
}
return succeeded;
145
146
}
147
int
148
149
SDL_SetGammaRamp(const Uint16 * red, const Uint16 * green,
const Uint16 * blue)
150
{
151
SDL_VideoDevice *_this = SDL_GetVideoDevice();
152
153
154
155
int succeeded;
/* Lazily allocate the gamma tables */
if (!SDL_CurrentWindow.gamma) {
156
SDL_GetGammaRamp(0, 0, 0);
157
158
159
160
}
/* Fill the gamma table with the new values */
if (red) {
161
162
SDL_memcpy(&SDL_CurrentWindow.gamma[0 * 256], red,
256 * sizeof(*SDL_CurrentWindow.gamma));
163
164
}
if (green) {
165
166
SDL_memcpy(&SDL_CurrentWindow.gamma[1 * 256], green,
256 * sizeof(*SDL_CurrentWindow.gamma));
167
168
}
if (blue) {
169
170
SDL_memcpy(&SDL_CurrentWindow.gamma[2 * 256], blue,
256 * sizeof(*SDL_CurrentWindow.gamma));
171
172
173
174
}
/* Try to set the gamma ramp in the driver */
succeeded = -1;
175
if (_this && _this->SetGammaRamp) {
176
succeeded = _this->SetGammaRamp(_this, SDL_CurrentWindow.gamma);
177
} else {
178
SDL_SetError("Gamma ramp manipulation not supported");
179
180
}
return succeeded;
181
182
}
183
int
184
SDL_GetGammaRamp(Uint16 * red, Uint16 * green, Uint16 * blue)
185
{
186
SDL_VideoDevice *_this = SDL_GetVideoDevice();
187
188
189
190
/* Lazily allocate the gamma table */
if (!SDL_CurrentWindow.gamma) {
SDL_CurrentWindow.gamma =
191
SDL_malloc(3 * 256 * sizeof(*SDL_CurrentWindow.gamma));
192
if (!SDL_CurrentWindow.gamma) {
193
SDL_OutOfMemory();
194
195
return -1;
}
196
if (_this && _this->GetGammaRamp) {
197
/* Get the real hardware gamma */
198
_this->GetGammaRamp(_this, SDL_CurrentWindow.gamma);
199
200
201
202
203
204
205
206
207
208
209
210
211
} else {
/* Assume an identity gamma */
int i;
for (i = 0; i < 256; ++i) {
SDL_CurrentWindow.gamma[0 * 256 + i] = (i << 8) | i;
SDL_CurrentWindow.gamma[1 * 256 + i] = (i << 8) | i;
SDL_CurrentWindow.gamma[2 * 256 + i] = (i << 8) | i;
}
}
}
/* Just copy from our internal table */
if (red) {
212
213
SDL_memcpy(red, &SDL_CurrentWindow.gamma[0 * 256],
256 * sizeof(*red));
214
215
}
if (green) {
216
217
SDL_memcpy(green, &SDL_CurrentWindow.gamma[1 * 256],
256 * sizeof(*green));
218
219
}
if (blue) {
220
221
SDL_memcpy(blue, &SDL_CurrentWindow.gamma[2 * 256],
256 * sizeof(*blue));
222
223
}
return 0;
224
}
225
226
/* vi: set ts=4 sw=4 expandtab: */