summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBertram <bertram@cegetel.net>2009-08-15 01:49:18 +0200
committerBertram <bertram@cegetel.net>2009-08-15 01:49:18 +0200
commitb45392a7cde35aac471813beec94686a8ec240ca (patch)
tree060351f1e148b2787d52f2fdc89e621f0acc87aa
parent9d1fbb5a538b3c5a1ba7d5ab55f39033ddb880f1 (diff)
downloadmana-b45392a7cde35aac471813beec94686a8ec240ca.tar.gz
mana-b45392a7cde35aac471813beec94686a8ec240ca.tar.bz2
mana-b45392a7cde35aac471813beec94686a8ec240ca.tar.xz
mana-b45392a7cde35aac471813beec94686a8ec240ca.zip
Mantis #783: Fixed window opacity breaks in software (SDL) mode.
-rw-r--r--src/resources/image.cpp100
-rw-r--r--src/resources/image.h13
2 files changed, 74 insertions, 39 deletions
diff --git a/src/resources/image.cpp b/src/resources/image.cpp
index a9005509..877bb998 100644
--- a/src/resources/image.cpp
+++ b/src/resources/image.cpp
@@ -27,6 +27,7 @@
#include <SDL_image.h>
#include "resources/sdlrescalefacility.h"
+#include <assert.h>
#ifdef USE_OPENGL
bool Image::mUseOpenGL = false;
@@ -34,9 +35,11 @@ int Image::mTextureType = 0;
int Image::mTextureSize = 0;
#endif
-Image::Image(SDL_Surface *image):
+Image::Image(SDL_Surface *image, bool hasAlphaChannel, Uint8 *alphaChannel):
mAlpha(1.0f),
- mSDLSurface(image)
+ mSDLSurface(image),
+ mHasAlphaChannel(hasAlphaChannel),
+ mAlphaChannel(alphaChannel)
{
#ifdef USE_OPENGL
mGLImage = 0;
@@ -52,7 +55,6 @@ Image::Image(SDL_Surface *image):
mBounds.w = mSDLSurface->w;
mBounds.h = mSDLSurface->h;
- mHasAlphaChannel = hasAlphaChannel();
mLoaded = true;
}
else
@@ -62,9 +64,10 @@ Image::Image(SDL_Surface *image):
#ifdef USE_OPENGL
Image::Image(GLuint glimage, int width, int height, int texWidth, int texHeight):
- mAlpha(1.0),
+ mAlpha(1.0f),
mHasAlphaChannel(true),
mSDLSurface(0),
+ mAlphaChannel(0),
mGLImage(glimage),
mTexWidth(texWidth),
mTexHeight(texHeight)
@@ -169,6 +172,9 @@ void Image::unload()
// Free the image surface.
SDL_FreeSurface(mSDLSurface);
mSDLSurface = NULL;
+
+ delete[] mAlphaChannel;
+ mAlphaChannel = NULL;
}
#ifdef USE_OPENGL
@@ -199,44 +205,49 @@ bool Image::hasAlphaChannel()
return true;
#endif
- if (!mSDLSurface)
- return false;
+ return false;
+}
- bool hasAlpha = false;
+void Image::setAlpha(float alpha)
+{
+ if (mAlpha == alpha)
+ return;
+
+ if (alpha < 0.0f || alpha > 1.0f)
+ return;
- if (mSDLSurface->format->BitsPerPixel == 32)
+ mAlpha = alpha;
+
+ if (mSDLSurface)
{
- // Figure out whether the image uses its alpha layer
- for (int i = 0; i < mSDLSurface->w * mSDLSurface->h; ++i)
+ if (!hasAlphaChannel())
{
- Uint8 r, g, b, a;
- SDL_GetRGBA(
- ((Uint32*) mSDLSurface->pixels)[i],
- mSDLSurface->format,
- &r, &g, &b, &a);
-
- if (a != 255)
- {
- hasAlpha = true;
- break;
- }
+ // Set the alpha value this image is drawn at
+ SDL_SetAlpha(mSDLSurface, SDL_SRCALPHA, (int) (255 * mAlpha));
}
- }
+ else
+ {
+ if (SDL_MUSTLOCK(mSDLSurface))
+ SDL_LockSurface(mSDLSurface);
- return hasAlpha;
-}
+ for (int i = 0; i < mSDLSurface->w * mSDLSurface->h; ++i)
+ {
+ Uint8 r, g, b, a;
+ SDL_GetRGBA(
+ ((Uint32*) mSDLSurface->pixels)[i],
+ mSDLSurface->format,
+ &r, &g, &b, &a);
-void Image::setAlpha(float a)
-{
- if (mAlpha == a)
- return;
+ a = (Uint8) (mAlphaChannel[i] * mAlpha);
- mAlpha = a;
+ // Here is the pixel we want to set
+ ((Uint32 *)(mSDLSurface->pixels))[i] =
+ SDL_MapRGBA(mSDLSurface->format, r, g, b, a);
+ }
- if (mSDLSurface)
- {
- // Set the alpha value this image is drawn at
- SDL_SetAlpha(mSDLSurface, SDL_SRCALPHA, (int) (255 * mAlpha));
+ if (SDL_MUSTLOCK(mSDLSurface))
+ SDL_UnlockSurface(mSDLSurface);
+ }
}
}
@@ -353,6 +364,9 @@ Image *Image::_SDLload(SDL_Surface *tmpImage)
bool hasAlpha = false;
+ // The alpha channel to be filled with alpha values
+ Uint8 *alphaChannel = new Uint8[tmpImage->w * tmpImage->h];
+
if (tmpImage->format->BitsPerPixel == 32)
{
// Figure out whether the image uses its alpha layer
@@ -365,10 +379,9 @@ Image *Image::_SDLload(SDL_Surface *tmpImage)
&r, &g, &b, &a);
if (a != 255)
- {
hasAlpha = true;
- break;
- }
+
+ alphaChannel[i] = a;
}
}
@@ -378,15 +391,23 @@ Image *Image::_SDLload(SDL_Surface *tmpImage)
if (hasAlpha)
image = SDL_DisplayFormatAlpha(tmpImage);
else
+ {
image = SDL_DisplayFormat(tmpImage);
+ // We also delete the alpha channel since
+ // it's not used.
+ delete[] alphaChannel;
+ alphaChannel = NULL;
+ }
+
if (!image)
{
logger->log("Error: Image convert failed.");
+ delete[] alphaChannel;
return NULL;
}
- return new Image(image);
+ return new Image(image, hasAlpha, alphaChannel);
}
#ifdef USE_OPENGL
@@ -537,6 +558,9 @@ SubImage::SubImage(Image *parent, SDL_Surface *image,
{
mParent->incRef();
+ mHasAlphaChannel = mParent->hasAlphaChannel();
+ mAlphaChannel = mParent->SDLgetAlphaChannel();
+
// Set up the rectangle.
mBounds.x = x;
mBounds.y = y;
@@ -565,6 +589,8 @@ SubImage::~SubImage()
{
// Avoid destruction of the image
mSDLSurface = 0;
+ // Avoid possible destruction of its alpha channel
+ mAlphaChannel = 0;
#ifdef USE_OPENGL
mGLImage = 0;
#endif
diff --git a/src/resources/image.h b/src/resources/image.h
index dfa319ab..9c0f9da7 100644
--- a/src/resources/image.h
+++ b/src/resources/image.h
@@ -118,7 +118,7 @@ class Image : public Resource
/**
* Tells if the image has got an alpha channel
- * @return true if OpenGL, false if SDL.
+ * @return true if it's true, false otherwise.
*/
bool hasAlphaChannel();
@@ -163,6 +163,12 @@ class Image : public Resource
*/
Image *SDLmerge(Image *image, int x, int y);
+ /**
+ * Get the alpha Channel of a SDL surface.
+ */
+ Uint8 *SDLgetAlphaChannel() const
+ { return mAlphaChannel; }
+
#ifdef USE_OPENGL
// OpenGL only public functions
@@ -194,13 +200,16 @@ class Image : public Resource
// -----------------------
/** SDL Constructor */
- Image(SDL_Surface *image);
+ Image(SDL_Surface *image, bool hasAlphaChannel = false,
+ Uint8 *alphaChannel = NULL);
/** SDL_Surface to SDL_Surface Image loader */
static Image *_SDLload(SDL_Surface *tmpImage);
SDL_Surface *mSDLSurface;
+ /** Alpha Channel pointer used for 32bit based SDL surfaces */
+ Uint8 *mAlphaChannel;
// -----------------------
// OpenGL protected members