Hi,
Here is some thoughts on code to make compositing gamma correct. I
think that the performance won't be too much of an issue, although there
is room for improvement. I'm not at all sure where this code should go
(like, when should we build the tables), but the way you use it is
pretty easy, I provide an FbOverU_Colour macro so you just have to
substitute this whenever interpolating colour, but NOT when calculating
alpha! :)
CARD32
fbOver (CARD32 x, CARD32 y)
{
CARD16 a = ~x >> 24;
CARD16 t;
CARD32 m,n,o,p;
m = FbOverU_Colour(x,y,0,a,t);
n = FbOverU_Colour(x,y,8,a,t);
o = FbOverU_Colour(x,y,16,a,t);
p = FbOverU(x,y,24,a,t);
return m|n|o|p;
}
One concern I have is that Blinn's division-by-255 method
(((a*b+128)*257)>>16) isn't accurate up to the 16 bit case (but is
completely accurate in the 8-bit case), so I need to see if maybe we
could get away with like 14-bit accuracy or something and still keep
those gains.
I'll post a proper patch when I get a chance to do one and test it,
but I thought I'd send this code here and see if someone else wants to
tell me if this improves things. :) We'd also need to export the
gamma value so it can be changed at runtime.
-Billy
static const double display_gamma = 2.2;
static double calc_intensity_to_voltage( double val )
{
if( val <= 0.018 ) {
return 4.5 * val;
}
return ( ( 1.099 * pow( val, 1.0 / display_gamma ) ) - 0.099 );
}
static double calc_voltage_to_intensity( double val )
{
if( val <= 0.081 ) {
return val / 4.5;
}
return pow( ( val + 0.099 ) / 1.099, display_gamma );
}
static unsigned int voltage_to_intensity[ 256 ];
static unsigned char intensity_to_voltage[ 65536 ];
static int gamma_tables_built = 0;
static void build_gamma_tables( void )
{
int i;
if( gamma_tables_built ) return;
for( i = 0; i < 256; i++ ) {
double curval = (double) i / 255.0;
double result = calc_voltage_to_intensity( curval );
voltage_to_intensity[ i ] = (unsigned int) ( ( result * 65535.0 ) + 0.5 );
}
for( i = 0; i < 65536; i++ ) {
double curval = (double) i / 65535.0;
double result = calc_intensity_to_voltage( curval );
intensity_to_voltage[ i ] = (unsigned int) ( ( result * 255.0 ) + 0.5 );
}
gamma_tables_built = 1;
}
#define FbOverU_Colour(x,y,i,a,t) ((t) =
intensity_to_voltage[FbIntMult(voltage_to_intensity[FbGet8(y,i)],(a),(t)) +
voltage_to_intensity[FbGet8(x,i)]],\
(CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i))
--
Billy Biggs
[EMAIL PROTECTED]
_______________________________________________
Render mailing list
[EMAIL PROTECTED]
http://XFree86.Org/mailman/listinfo/render