Fix blit_rgba_to_rgba: converting channels that were at least 1bpp
to a higher bit depth resulted in 0s. This caused banners to be transparent on Macs. This also fixes scaling: scale colors instead of truncating them. This is a little slower; I might need to add an optimized blit for the d3d movie code path ...
This commit is contained in:
@@ -516,29 +516,58 @@ static void blit_rgba_to_rgba( const RageSurface *src_surf, const RageSurface *d
|
|||||||
RageSurfaceUtils::GetBitsPerChannel(src_surf->format, src_bits);
|
RageSurfaceUtils::GetBitsPerChannel(src_surf->format, src_bits);
|
||||||
RageSurfaceUtils::GetBitsPerChannel(dst_surf->format, dst_bits);
|
RageSurfaceUtils::GetBitsPerChannel(dst_surf->format, dst_bits);
|
||||||
|
|
||||||
const int rshifts[4] = {
|
/* XXX: We should store the shifts and masks as an array in RageSurfaceFormat. */
|
||||||
src_surf->format->Rshift + src_bits[0] - dst_bits[0],
|
const int src_shifts[4] = {
|
||||||
src_surf->format->Gshift + src_bits[1] - dst_bits[1],
|
src_surf->format->Rshift,
|
||||||
src_surf->format->Bshift + src_bits[2] - dst_bits[2],
|
src_surf->format->Gshift,
|
||||||
src_surf->format->Ashift + src_bits[3] - dst_bits[3],
|
src_surf->format->Bshift,
|
||||||
|
src_surf->format->Ashift,
|
||||||
};
|
};
|
||||||
const int lshifts[4] = {
|
|
||||||
|
const int dst_shifts[4] = {
|
||||||
dst_surf->format->Rshift,
|
dst_surf->format->Rshift,
|
||||||
dst_surf->format->Gshift,
|
dst_surf->format->Gshift,
|
||||||
dst_surf->format->Bshift,
|
dst_surf->format->Bshift,
|
||||||
dst_surf->format->Ashift,
|
dst_surf->format->Ashift,
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint32_t masks[4] = {
|
const uint32_t src_masks[4] =
|
||||||
|
{
|
||||||
src_surf->format->Rmask,
|
src_surf->format->Rmask,
|
||||||
src_surf->format->Gmask,
|
src_surf->format->Gmask,
|
||||||
src_surf->format->Bmask,
|
src_surf->format->Bmask,
|
||||||
src_surf->format->Amask
|
src_surf->format->Amask
|
||||||
};
|
};
|
||||||
|
|
||||||
int ormask = 0;
|
const uint32_t dst_masks[4] =
|
||||||
if( src_surf->format->Amask == 0 )
|
{
|
||||||
ormask = dst_surf->format->Amask;
|
dst_surf->format->Rmask,
|
||||||
|
dst_surf->format->Gmask,
|
||||||
|
dst_surf->format->Bmask,
|
||||||
|
dst_surf->format->Amask
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t lookup[4][256];
|
||||||
|
for( int c = 0; c < 4; ++c )
|
||||||
|
{
|
||||||
|
const uint32_t max_src_val = src_masks[c] >> src_shifts[c];
|
||||||
|
const uint32_t max_dst_val = dst_masks[c] >> dst_shifts[c];
|
||||||
|
ASSERT( max_src_val <= 0xFF );
|
||||||
|
ASSERT( max_dst_val <= 0xFF );
|
||||||
|
|
||||||
|
if( src_masks[c] == 0 )
|
||||||
|
{
|
||||||
|
/* The source is missing a channel. Alpha defaults to opaque, other
|
||||||
|
* channels default to 0. */
|
||||||
|
if( c == 3 )
|
||||||
|
lookup[c][0] = (uint8_t) max_dst_val;
|
||||||
|
else
|
||||||
|
lookup[c][0] = 0;
|
||||||
|
} else {
|
||||||
|
for( uint32_t i = 0; i <= max_src_val; ++i )
|
||||||
|
lookup[c][i] = (uint8_t) SCALE( i, 0, max_src_val, 0, max_dst_val );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while( height-- )
|
while( height-- )
|
||||||
{
|
{
|
||||||
@@ -547,15 +576,13 @@ static void blit_rgba_to_rgba( const RageSurface *src_surf, const RageSurface *d
|
|||||||
{
|
{
|
||||||
unsigned int pixel = RageSurfaceUtils::decodepixel( src, src_surf->format->BytesPerPixel );
|
unsigned int pixel = RageSurfaceUtils::decodepixel( src, src_surf->format->BytesPerPixel );
|
||||||
|
|
||||||
/* Convert pixel to the destination RGBA. */
|
/* Convert pixel to the destination format. */
|
||||||
unsigned int opixel = 0;
|
unsigned int opixel = 0;
|
||||||
opixel |= (pixel & masks[0]) >> rshifts[0] << lshifts[0];
|
for( int c = 0; c < 4; ++c )
|
||||||
opixel |= (pixel & masks[1]) >> rshifts[1] << lshifts[1];
|
{
|
||||||
opixel |= (pixel & masks[2]) >> rshifts[2] << lshifts[2];
|
int src = (pixel & src_masks[c]) >> src_shifts[c];
|
||||||
opixel |= (pixel & masks[3]) >> rshifts[3] << lshifts[3];
|
opixel |= lookup[c][src] << dst_shifts[c];
|
||||||
|
}
|
||||||
// Correct surfaces that don't have an alpha channel.
|
|
||||||
opixel |= ormask;
|
|
||||||
|
|
||||||
/* Store it. */
|
/* Store it. */
|
||||||
RageSurfaceUtils::encodepixel( dst, dst_surf->format->BytesPerPixel, opixel );
|
RageSurfaceUtils::encodepixel( dst, dst_surf->format->BytesPerPixel, opixel );
|
||||||
|
|||||||
Reference in New Issue
Block a user