Automatically figure out if we can use 0alpha or 1alpha. I'll remove the
old code once the new code is stable.
This commit is contained in:
@@ -148,24 +148,6 @@ void RageBitmapTexture::Reload()
|
||||
*/
|
||||
SDL_Surface *RageBitmapTexture::CreateImg(int &pixfmt)
|
||||
{
|
||||
// look in the file name for a format hints
|
||||
CString HintString = GetFilePath();
|
||||
HintString.MakeLower();
|
||||
|
||||
if( HintString.Find("4alphaonly") != -1 ) m_ActualID.iTransparencyOnly = 4;
|
||||
else if( HintString.Find("8alphaonly") != -1 ) m_ActualID.iTransparencyOnly = 8;
|
||||
else if( HintString.Find("no alpha") != -1 ) m_ActualID.iAlphaBits = 0;
|
||||
else if( HintString.Find("0alpha") != -1 ) m_ActualID.iAlphaBits = 0;
|
||||
else if( HintString.Find("1 alpha") != -1 ) m_ActualID.iAlphaBits = 1;
|
||||
else if( HintString.Find("1alpha") != -1 ) m_ActualID.iAlphaBits = 1;
|
||||
if( HintString.Find("dither") != -1 ) m_ActualID.bDither = true;
|
||||
|
||||
if( m_ActualID.iTransparencyOnly )
|
||||
{
|
||||
/* Treat the image as 32-bit, so we don't lose any alpha precision. */
|
||||
m_ActualID.iColorDepth = 32;
|
||||
}
|
||||
|
||||
/* Load the image into an SDL surface. */
|
||||
SDL_Surface *img = IMG_Load(GetFilePath());
|
||||
|
||||
@@ -192,6 +174,35 @@ SDL_Surface *RageBitmapTexture::CreateImg(int &pixfmt)
|
||||
SDL_SetColorKey( img, SDL_SRCCOLORKEY, color);
|
||||
}
|
||||
|
||||
{
|
||||
/* This should eventually obsolete 8alphaonly, 0alpha and 1alpha,
|
||||
* and remove the need to special case background loads. Do this
|
||||
* after setting the color key for paletted images; it'll also return
|
||||
* TRAIT_NO_TRANSPARENCY if the color key is never used. */
|
||||
int traits = FindSurfaceTraits(img);
|
||||
if(traits & TRAIT_NO_TRANSPARENCY) m_ActualID.iAlphaBits = 0;
|
||||
else if(traits & TRAIT_BOOL_TRANSPARENCY) m_ActualID.iAlphaBits = 1;
|
||||
if(traits & TRAIT_WHITE_ONLY) m_ActualID.iTransparencyOnly = 8;
|
||||
}
|
||||
|
||||
// look in the file name for a format hints
|
||||
CString HintString = GetFilePath();
|
||||
HintString.MakeLower();
|
||||
|
||||
if( HintString.Find("4alphaonly") != -1 ) m_ActualID.iTransparencyOnly = 4;
|
||||
else if( HintString.Find("8alphaonly") != -1 ) m_ActualID.iTransparencyOnly = 8;
|
||||
// else if( HintString.Find("no alpha") != -1 ) m_ActualID.iAlphaBits = 0;
|
||||
// else if( HintString.Find("0alpha") != -1 ) m_ActualID.iAlphaBits = 0;
|
||||
// else if( HintString.Find("1 alpha") != -1 ) m_ActualID.iAlphaBits = 1;
|
||||
// else if( HintString.Find("1alpha") != -1 ) m_ActualID.iAlphaBits = 1;
|
||||
if( HintString.Find("dither") != -1 ) m_ActualID.bDither = true;
|
||||
|
||||
if( m_ActualID.iTransparencyOnly )
|
||||
{
|
||||
/* Treat the image as 32-bit, so we don't lose any alpha precision. */
|
||||
m_ActualID.iColorDepth = 32;
|
||||
}
|
||||
|
||||
GLenum fmtTexture;
|
||||
/* Figure out which texture format to use. */
|
||||
if( m_ActualID.iColorDepth == 16 )
|
||||
@@ -210,9 +221,6 @@ SDL_Surface *RageBitmapTexture::CreateImg(int &pixfmt)
|
||||
/* Don't use more than we were hinted to. */
|
||||
src_alpha_bits = min( m_ActualID.iAlphaBits, src_alpha_bits );
|
||||
|
||||
/* XXX Scan the image, and see if it actually uses its alpha channel/color key
|
||||
* (if any). Reduce to 1 or 0 bits of alpha if possible. */
|
||||
|
||||
switch( src_alpha_bits ) {
|
||||
case 0:
|
||||
case 1:
|
||||
@@ -410,12 +418,17 @@ retry:
|
||||
/* (don't change internalfmt) */
|
||||
}
|
||||
|
||||
/* Override the internalformat with an alpha format if it was requested. */
|
||||
if(m_ActualID.iTransparencyOnly == 4)
|
||||
internalfmt = GL_ALPHA4;
|
||||
else if(m_ActualID.iTransparencyOnly == 8)
|
||||
internalfmt = GL_ALPHA8;
|
||||
else ASSERT(m_ActualID.iTransparencyOnly == 0);
|
||||
if(internalfmt != GL_COLOR_INDEX8_EXT)
|
||||
{
|
||||
/* Override the internalformat with an alpha format if it was requested.
|
||||
* Don't use iTransparencyOnly with paletted images; there's no point--paletted
|
||||
* images are as small or smaller (and the load will fail). */
|
||||
if(m_ActualID.iTransparencyOnly == 4)
|
||||
internalfmt = GL_ALPHA4;
|
||||
else if(m_ActualID.iTransparencyOnly == 8)
|
||||
internalfmt = GL_ALPHA8;
|
||||
else ASSERT(m_ActualID.iTransparencyOnly == 0);
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, internalfmt,
|
||||
m_iTextureWidth, m_iTextureHeight, 0,
|
||||
@@ -444,10 +457,17 @@ retry:
|
||||
SDL_FreeSurface(img);
|
||||
|
||||
CreateFrameRects();
|
||||
|
||||
// LOG->Trace( "RageBitmapTexture: Loaded '%s' (%ux%u) from disk. bStretch = %d, source %d,%d; image %d,%d.",
|
||||
// m_sFilePath.GetString(), GetTextureWidth(), GetTextureHeight(),
|
||||
// bStretch, m_iSourceWidth, m_iSourceHeight,
|
||||
// m_iImageWidth, m_iImageHeight);
|
||||
CString props = " ";
|
||||
if(m_ActualID.iAlphaBits == 0) props += "opaque ";
|
||||
if(m_ActualID.iAlphaBits == 1) props += "matte ";
|
||||
if(m_ActualID.iTransparencyOnly) props += "mask ";
|
||||
if(m_ActualID.bStretch) props += "stretch ";
|
||||
if(m_ActualID.bDither) props += "dither ";
|
||||
if(IsPackedPixelFormat(pixfmt)) props += "paletted ";
|
||||
props.erase(props.size()-1);
|
||||
LOG->Trace( "RageBitmapTexture: Loaded '%s' (%ux%u); %s, source %d,%d; image %d,%d.",
|
||||
m_ActualID.filename.GetString(), GetTextureWidth(), GetTextureHeight(),
|
||||
props.GetString(), m_iSourceWidth, m_iSourceHeight,
|
||||
m_iImageWidth, m_iImageHeight);
|
||||
}
|
||||
|
||||
|
||||
@@ -232,6 +232,7 @@ SDL_Surface *SDL_CreateRGBSurfaceSane
|
||||
return SDL_CreateRGBSurface(flags, width, height, depth,
|
||||
Rmask, Gmask, Bmask, Amask);
|
||||
}
|
||||
|
||||
static void FindAlphaRGB(const SDL_Surface *img, Uint8 &r, Uint8 &g, Uint8 &b, bool reverse)
|
||||
{
|
||||
/* If we have no alpha or no color key, there's no alpha color. */
|
||||
@@ -339,3 +340,110 @@ void FixHiddenAlpha(SDL_Surface *img)
|
||||
|
||||
SetAlphaRGB(img, r, g, b);
|
||||
}
|
||||
|
||||
/* XXX: currently only TRAIT_NO_TRANSPARENCY and TRAIT_BOOL_TRANSPARENCY work. */
|
||||
/* Find various traits of a surface. Do these all at once, so we only have to
|
||||
* iterate the surface once. */
|
||||
|
||||
/* We could theoretically do a test to see if an image fits in GL_ALPHA4,
|
||||
* by looking at the least significant bits of each alpha value. This is
|
||||
* not likely to ever find a match, though, so don't bother; only use 8alphaonly
|
||||
* if it's explicitly enabled.
|
||||
*
|
||||
* XXX: We could do the FindAlphaRGB search here, too, but we need that information
|
||||
* in a different place. */
|
||||
// #define TRAIT_CONSISTENT_TRANSPARENT_COLOR 0x0008
|
||||
|
||||
int FindSurfaceTraits(const SDL_Surface *img)
|
||||
// Uint8 AlphaColor[3])
|
||||
{
|
||||
// bool HaveAlphaValue = false; /* whether ar, ag, ab is valid */
|
||||
// bool HaveConsistentAlphaValue = true;
|
||||
bool HaveTransparency = false;
|
||||
bool HaveTranslucensy = false;
|
||||
// bool WhiteOnly = true;
|
||||
|
||||
for(int y = 0; y < img->h; ++y)
|
||||
{
|
||||
Uint8 *row = (Uint8 *)img->pixels + img->pitch*y;
|
||||
// bool FirstVisible = true;
|
||||
|
||||
for(int x = 0; x < img->w; ++x)
|
||||
{
|
||||
Uint32 val = decodepixel(row, img->format->BytesPerPixel);
|
||||
|
||||
bool Transparent = false;
|
||||
bool Translucent = false;
|
||||
if( img->format->BitsPerPixel == 8 ) {
|
||||
if(img->flags & SDL_SRCCOLORKEY && val == img->format->colorkey )
|
||||
Transparent = true;
|
||||
} else if(img->format->Amask) {
|
||||
Uint32 masked_alpha = val & img->format->Amask;
|
||||
if(masked_alpha == 0) Transparent = true;
|
||||
else if(masked_alpha != img->format->Amask) Translucent = true;
|
||||
}
|
||||
|
||||
if(Transparent) HaveTransparency = true;
|
||||
if(Translucent) HaveTranslucensy = true;
|
||||
|
||||
#if 0
|
||||
/* Hmm. This doesn't quite work. For example, the ScreenCompany
|
||||
* shadow is actually black; we load it as 8alphaonly, which discards
|
||||
* the black completely (making it a white shadow), and then we make
|
||||
* it black again by setting the diffuse color to black. This is hard
|
||||
* to generalize. I guess we could just make the shadow white, but
|
||||
* that's a little ugly to edit.
|
||||
*
|
||||
* Also, for some reason, the font borders are actually a combination
|
||||
* of a shade of gray and some alpha value. Those need to be simplified
|
||||
* to white and some alpha value (multiply the luma by alpha), but
|
||||
* that's another special case.
|
||||
*
|
||||
* So, this doesn't actually help anything right now, and we still
|
||||
* need 8alphaonly. */
|
||||
if( img->format->BitsPerPixel != 8 ) {
|
||||
/* If the pixel isn't transparent, and isn't completely white: */
|
||||
if(!Transparent &&
|
||||
(val & img->format->Rmask) != img->format->Rmask &&
|
||||
(val & img->format->Gmask) != img->format->Gmask &&
|
||||
(val & img->format->Bmask) != img->format->Bmask)
|
||||
WhiteOnly=false;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* Is this the first non-invisible pixel on this row? */
|
||||
if(!Invisible && FirstVisible)
|
||||
{
|
||||
FirstVisible = false;
|
||||
|
||||
Uint8 r, g, b;
|
||||
SDL_GetRGB(val, img->format, &r, &g, &b);
|
||||
|
||||
if(!HaveAlphaValue) {
|
||||
/* We don't have the border color yet; set it. */
|
||||
HaveAlphaValue = true;
|
||||
AlphaColor[0] = r;
|
||||
AlphaColor[1] = g;
|
||||
AlphaColor[2] = b;
|
||||
} else if(HaveConsistentAlphaValue) {
|
||||
/* We already have an alpha color from the previous row;
|
||||
* if it's not the same, it's inconsistent. */
|
||||
if(r != AlphaColor[0] || g != AlphaColor[1] || b != AlphaColor[2])
|
||||
HaveConsistentAlphaValue = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
row += img->format->BytesPerPixel;
|
||||
}
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
// if(HaveConsistentAlphaValue) ret |= TRAIT_CONSISTENT_TRANSPARENT_COLOR;
|
||||
if(!HaveTransparency) ret |= TRAIT_NO_TRANSPARENCY;
|
||||
if(!HaveTranslucensy) ret |= TRAIT_BOOL_TRANSPARENCY;
|
||||
// if(WhiteOnly) ret |= TRAIT_WHITE_ONLY;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,17 @@ SDL_Surface *SDL_CreateRGBSurfaceSane
|
||||
|
||||
void FixHiddenAlpha(SDL_Surface *img);
|
||||
|
||||
/* The surface contains no transparent pixels and/or never uses its color
|
||||
* key, so it doesn't need any alpha bits at all. */
|
||||
#define TRAIT_NO_TRANSPARENCY 0x0001 /* 0alpha */
|
||||
/* The surface contains only transparent values of 0 or 1; no translucency.
|
||||
* It only needs one bit of alpha. */
|
||||
#define TRAIT_BOOL_TRANSPARENCY 0x0002 /* 1alpha */
|
||||
/* All opaque pixels in this image are completely white, so it doesn't need
|
||||
* any color bits at all; use a GL_ALPHA8 and only store the transparency. */
|
||||
#define TRAIT_WHITE_ONLY 0x0004 /* 8alphaonly */
|
||||
int FindSurfaceTraits(const SDL_Surface *img);
|
||||
|
||||
struct char_traits_Sint32: public char_traits<Sint32>
|
||||
{
|
||||
static Sint32 *copy(Sint32 *s, const Sint32 *p, size_t n)
|
||||
|
||||
Reference in New Issue
Block a user