symbian-qemu-0.9.1-12/libsdl-trunk/src/video/SDL_gamma.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     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     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     Lesser General Public License for more details.
       
    14 
       
    15     You should have received a copy of the GNU Lesser General Public
       
    16     License along with this library; if not, write to the Free Software
       
    17     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 /* Gamma correction support */
       
    25 
       
    26 #ifdef HAVE_MATH_H
       
    27 #include <math.h>	/* Used for calculating gamma ramps */
       
    28 #else
       
    29 /* Math routines from uClibc: http://www.uclibc.org */
       
    30 #include "math_private.h"
       
    31 #include "e_sqrt.h"
       
    32 #include "e_pow.h"
       
    33 #include "e_log.h"
       
    34 #define pow(x, y)	__ieee754_pow(x, y)
       
    35 #define log(x)		__ieee754_log(x)
       
    36 #endif
       
    37 
       
    38 #include "SDL_sysvideo.h"
       
    39 
       
    40 
       
    41 static void CalculateGammaRamp(float gamma, Uint16 *ramp)
       
    42 {
       
    43 	int i;
       
    44 
       
    45 	/* 0.0 gamma is all black */
       
    46 	if ( gamma <= 0.0f ) {
       
    47 		for ( i=0; i<256; ++i ) {
       
    48 			ramp[i] = 0;
       
    49 		}
       
    50 		return;
       
    51 	} else
       
    52 	/* 1.0 gamma is identity */
       
    53 	if ( gamma == 1.0f ) {
       
    54 		for ( i=0; i<256; ++i ) {
       
    55 			ramp[i] = (i << 8) | i;
       
    56 		}
       
    57 		return;
       
    58 	} else
       
    59 	/* Calculate a real gamma ramp */
       
    60 	{ int value;
       
    61 		gamma = 1.0f / gamma;
       
    62 		for ( i=0; i<256; ++i ) {
       
    63 			value = (int)(pow((double)i/256.0, gamma)*65535.0+0.5);
       
    64 			if ( value > 65535 ) {
       
    65 				value = 65535;
       
    66 			}
       
    67 			ramp[i] = (Uint16)value;
       
    68 		}
       
    69 	}
       
    70 }
       
    71 static void CalculateGammaFromRamp(float *gamma, Uint16 *ramp)
       
    72 {
       
    73 	/* The following is adapted from a post by Garrett Bass on OpenGL
       
    74 	   Gamedev list, March 4, 2000.
       
    75 	 */
       
    76 	float sum = 0.0f;
       
    77 	int i, count = 0;
       
    78 
       
    79 	*gamma = 1.0;
       
    80 	for ( i = 1; i < 256; ++i ) {
       
    81 	    if ( (ramp[i] != 0) && (ramp[i] != 65535) ) {
       
    82 	        double B = (double)i / 256.0;
       
    83 	        double A = ramp[i] / 65535.0;
       
    84 	        sum += (float) ( log(A) / log(B) );
       
    85 	        count++;
       
    86 	    }
       
    87 	}
       
    88 	if ( count && sum > 0.0f ) {
       
    89 		*gamma = 1.0f / (sum / count);
       
    90 	}
       
    91 }
       
    92 
       
    93 int SDL_SetGamma(float red, float green, float blue)
       
    94 {
       
    95 	int succeeded;
       
    96 	SDL_VideoDevice *video = current_video;
       
    97 	SDL_VideoDevice *this  = current_video;	
       
    98 
       
    99 	succeeded = -1;
       
   100 	/* Prefer using SetGammaRamp(), as it's more flexible */
       
   101 	{
       
   102 		Uint16 ramp[3][256];
       
   103 
       
   104 		CalculateGammaRamp(red, ramp[0]);
       
   105 		CalculateGammaRamp(green, ramp[1]);
       
   106 		CalculateGammaRamp(blue, ramp[2]);
       
   107 		succeeded = SDL_SetGammaRamp(ramp[0], ramp[1], ramp[2]);
       
   108 	}
       
   109 	if ( (succeeded < 0) && video->SetGamma ) {
       
   110 		SDL_ClearError();
       
   111 		succeeded = video->SetGamma(this, red, green, blue);
       
   112 	}
       
   113 	return succeeded;
       
   114 }
       
   115 
       
   116 /* Calculating the gamma by integrating the gamma ramps isn't exact,
       
   117    so this function isn't officially supported.
       
   118 */
       
   119 int SDL_GetGamma(float *red, float *green, float *blue)
       
   120 {
       
   121 	int succeeded;
       
   122 	SDL_VideoDevice *video = current_video;
       
   123 	SDL_VideoDevice *this  = current_video;	
       
   124 
       
   125 	succeeded = -1;
       
   126 	/* Prefer using GetGammaRamp(), as it's more flexible */
       
   127 	{
       
   128 		Uint16 ramp[3][256];
       
   129 
       
   130 		succeeded = SDL_GetGammaRamp(ramp[0], ramp[1], ramp[2]);
       
   131 		if ( succeeded >= 0 ) {
       
   132 			CalculateGammaFromRamp(red, ramp[0]);
       
   133 			CalculateGammaFromRamp(green, ramp[1]);
       
   134 			CalculateGammaFromRamp(blue, ramp[2]);
       
   135 		}
       
   136 	}
       
   137 	if ( (succeeded < 0) && video->GetGamma ) {
       
   138 		SDL_ClearError();
       
   139 		succeeded = video->GetGamma(this, red, green, blue);
       
   140 	}
       
   141 	return succeeded;
       
   142 }
       
   143 
       
   144 int SDL_SetGammaRamp(const Uint16 *red, const Uint16 *green, const Uint16 *blue)
       
   145 {
       
   146 	int succeeded;
       
   147 	SDL_VideoDevice *video = current_video;
       
   148 	SDL_VideoDevice *this  = current_video;	
       
   149 	SDL_Surface *screen = SDL_PublicSurface;
       
   150 
       
   151 	/* Verify the screen parameter */
       
   152 	if ( !screen ) {
       
   153 		SDL_SetError("No video mode has been set");
       
   154 		return -1;
       
   155 	}
       
   156 
       
   157 	/* Lazily allocate the gamma tables */
       
   158 	if ( ! video->gamma ) {
       
   159 		SDL_GetGammaRamp(0, 0, 0);
       
   160 	}
       
   161 
       
   162 	/* Fill the gamma table with the new values */
       
   163 	if ( red ) {
       
   164 		SDL_memcpy(&video->gamma[0*256], red, 256*sizeof(*video->gamma));
       
   165 	}
       
   166 	if ( green ) {
       
   167 		SDL_memcpy(&video->gamma[1*256], green, 256*sizeof(*video->gamma));
       
   168 	}
       
   169 	if ( blue ) {
       
   170 		SDL_memcpy(&video->gamma[2*256], blue, 256*sizeof(*video->gamma));
       
   171 	}
       
   172 
       
   173 	/* Gamma correction always possible on split palettes */
       
   174 	if ( (screen->flags & SDL_HWPALETTE) == SDL_HWPALETTE ) {
       
   175 		SDL_Palette *pal = screen->format->palette;
       
   176 
       
   177 		/* If physical palette has been set independently, use it */
       
   178 		if(video->physpal)
       
   179 		        pal = video->physpal;
       
   180 		      
       
   181 		SDL_SetPalette(screen, SDL_PHYSPAL,
       
   182 			       pal->colors, 0, pal->ncolors);
       
   183 		return 0;
       
   184 	}
       
   185 
       
   186 	/* Try to set the gamma ramp in the driver */
       
   187 	succeeded = -1;
       
   188 	if ( video->SetGammaRamp ) {
       
   189 		succeeded = video->SetGammaRamp(this, video->gamma);
       
   190 	} else {
       
   191 		SDL_SetError("Gamma ramp manipulation not supported");
       
   192 	}
       
   193 	return succeeded;
       
   194 }
       
   195 
       
   196 int SDL_GetGammaRamp(Uint16 *red, Uint16 *green, Uint16 *blue)
       
   197 {
       
   198 	SDL_VideoDevice *video = current_video;
       
   199 	SDL_VideoDevice *this  = current_video;	
       
   200 
       
   201 	/* Lazily allocate the gamma table */
       
   202 	if ( ! video->gamma ) {
       
   203 		video->gamma = SDL_malloc(3*256*sizeof(*video->gamma));
       
   204 		if ( ! video->gamma ) {
       
   205 			SDL_OutOfMemory();
       
   206 			return -1;
       
   207 		}
       
   208 		if ( video->GetGammaRamp ) {
       
   209 			/* Get the real hardware gamma */
       
   210 			video->GetGammaRamp(this, video->gamma);
       
   211 		} else {
       
   212 			/* Assume an identity gamma */
       
   213 			int i;
       
   214 			for ( i=0; i<256; ++i ) {
       
   215 				video->gamma[0*256+i] = (i << 8) | i;
       
   216 				video->gamma[1*256+i] = (i << 8) | i;
       
   217 				video->gamma[2*256+i] = (i << 8) | i;
       
   218 			}
       
   219 		}
       
   220 	}
       
   221 
       
   222 	/* Just copy from our internal table */
       
   223 	if ( red ) {
       
   224 		SDL_memcpy(red, &video->gamma[0*256], 256*sizeof(*red));
       
   225 	}
       
   226 	if ( green ) {
       
   227 		SDL_memcpy(green, &video->gamma[1*256], 256*sizeof(*green));
       
   228 	}
       
   229 	if ( blue ) {
       
   230 		SDL_memcpy(blue, &video->gamma[2*256], 256*sizeof(*blue));
       
   231 	}
       
   232 	return 0;
       
   233 }