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)
|
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. */
|
/* Load the image into an SDL surface. */
|
||||||
SDL_Surface *img = IMG_Load(GetFilePath());
|
SDL_Surface *img = IMG_Load(GetFilePath());
|
||||||
|
|
||||||
@@ -192,6 +174,35 @@ SDL_Surface *RageBitmapTexture::CreateImg(int &pixfmt)
|
|||||||
SDL_SetColorKey( img, SDL_SRCCOLORKEY, color);
|
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;
|
GLenum fmtTexture;
|
||||||
/* Figure out which texture format to use. */
|
/* Figure out which texture format to use. */
|
||||||
if( m_ActualID.iColorDepth == 16 )
|
if( m_ActualID.iColorDepth == 16 )
|
||||||
@@ -210,9 +221,6 @@ SDL_Surface *RageBitmapTexture::CreateImg(int &pixfmt)
|
|||||||
/* Don't use more than we were hinted to. */
|
/* Don't use more than we were hinted to. */
|
||||||
src_alpha_bits = min( m_ActualID.iAlphaBits, src_alpha_bits );
|
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 ) {
|
switch( src_alpha_bits ) {
|
||||||
case 0:
|
case 0:
|
||||||
case 1:
|
case 1:
|
||||||
@@ -410,12 +418,17 @@ retry:
|
|||||||
/* (don't change internalfmt) */
|
/* (don't change internalfmt) */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Override the internalformat with an alpha format if it was requested. */
|
if(internalfmt != GL_COLOR_INDEX8_EXT)
|
||||||
if(m_ActualID.iTransparencyOnly == 4)
|
{
|
||||||
internalfmt = GL_ALPHA4;
|
/* Override the internalformat with an alpha format if it was requested.
|
||||||
else if(m_ActualID.iTransparencyOnly == 8)
|
* Don't use iTransparencyOnly with paletted images; there's no point--paletted
|
||||||
internalfmt = GL_ALPHA8;
|
* images are as small or smaller (and the load will fail). */
|
||||||
else ASSERT(m_ActualID.iTransparencyOnly == 0);
|
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,
|
glTexImage2D(GL_TEXTURE_2D, 0, internalfmt,
|
||||||
m_iTextureWidth, m_iTextureHeight, 0,
|
m_iTextureWidth, m_iTextureHeight, 0,
|
||||||
@@ -444,10 +457,17 @@ retry:
|
|||||||
SDL_FreeSurface(img);
|
SDL_FreeSurface(img);
|
||||||
|
|
||||||
CreateFrameRects();
|
CreateFrameRects();
|
||||||
|
CString props = " ";
|
||||||
// LOG->Trace( "RageBitmapTexture: Loaded '%s' (%ux%u) from disk. bStretch = %d, source %d,%d; image %d,%d.",
|
if(m_ActualID.iAlphaBits == 0) props += "opaque ";
|
||||||
// m_sFilePath.GetString(), GetTextureWidth(), GetTextureHeight(),
|
if(m_ActualID.iAlphaBits == 1) props += "matte ";
|
||||||
// bStretch, m_iSourceWidth, m_iSourceHeight,
|
if(m_ActualID.iTransparencyOnly) props += "mask ";
|
||||||
// m_iImageWidth, m_iImageHeight);
|
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,
|
return SDL_CreateRGBSurface(flags, width, height, depth,
|
||||||
Rmask, Gmask, Bmask, Amask);
|
Rmask, Gmask, Bmask, Amask);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FindAlphaRGB(const SDL_Surface *img, Uint8 &r, Uint8 &g, Uint8 &b, bool reverse)
|
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. */
|
/* 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);
|
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);
|
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>
|
struct char_traits_Sint32: public char_traits<Sint32>
|
||||||
{
|
{
|
||||||
static Sint32 *copy(Sint32 *s, const Sint32 *p, size_t n)
|
static Sint32 *copy(Sint32 *s, const Sint32 *p, size_t n)
|
||||||
|
|||||||
Reference in New Issue
Block a user