diff options
Diffstat (limited to 'src/resources')
-rw-r--r-- | src/resources/ambientlayer.cpp | 22 | ||||
-rw-r--r-- | src/resources/image.cpp | 291 | ||||
-rw-r--r-- | src/resources/image.h | 58 |
3 files changed, 37 insertions, 334 deletions
diff --git a/src/resources/ambientlayer.cpp b/src/resources/ambientlayer.cpp index c31afbac..301927f8 100644 --- a/src/resources/ambientlayer.cpp +++ b/src/resources/ambientlayer.cpp @@ -33,25 +33,6 @@ AmbientLayer::AmbientLayer(Image *img, float parallax, mKeepRatio(keepRatio) { mImage->incRef(); - - if (keepRatio && !mImage->useOpenGL() - && defaultScreenWidth != 0 - && defaultScreenHeight != 0 - && graphics->getWidth() != defaultScreenWidth - && graphics->getHeight() != defaultScreenHeight) - { - // Rescale the overlay to keep the ratio as if we were on - // the default resolution... - Image *rescaledOverlay = mImage->SDLgetScaledImage( - (int) mImage->getWidth() / defaultScreenWidth * graphics->getWidth(), - (int) mImage->getHeight() / defaultScreenHeight * graphics->getHeight()); - - if (rescaledOverlay) - { - mImage->decRef(); - mImage = rescaledOverlay; - } - } } AmbientLayer::~AmbientLayer() @@ -86,7 +67,7 @@ void AmbientLayer::update(int timePassed, float dx, float dy) void AmbientLayer::draw(Graphics *graphics, int x, int y) { - if (!mImage->useOpenGL() || !mKeepRatio) + if (!mKeepRatio) graphics->drawImagePattern(mImage, (int) -mPosX, (int) -mPosY, x + (int) mPosX, y + (int) mPosY); else @@ -94,5 +75,4 @@ void AmbientLayer::draw(Graphics *graphics, int x, int y) (int) -mPosX, (int) -mPosY, x + (int) mPosX, y + (int) mPosY, (int) mImage->getWidth() / defaultScreenWidth * graphics->getWidth(), (int) mImage->getHeight() / defaultScreenHeight * graphics->getHeight()); - } diff --git a/src/resources/image.cpp b/src/resources/image.cpp index 7e592198..6f2609b0 100644 --- a/src/resources/image.cpp +++ b/src/resources/image.cpp @@ -29,10 +29,8 @@ #endif #include "log.h" -#include "configuration.h" #include <SDL_image.h> -#include <SDL_rotozoom.h> #ifdef USE_OPENGL bool Image::mUseOpenGL = false; @@ -40,47 +38,38 @@ bool Image::mPowerOfTwoTextures = true; int Image::mTextureType = 0; int Image::mTextureSize = 0; #endif -bool Image::mEnableAlphaCache = false; // The low CPU mode is disabled per default bool Image::mDisableTransparency = false; -Image::Image(SDL_Surface *image, bool hasAlphaChannel, Uint8 *alphaChannel): +SDL_Renderer *Image::mRenderer; + +Image::Image(SDL_Texture *texture, int width, int height): mAlpha(1.0f), - mSDLSurface(image), - mAlphaChannel(alphaChannel), - mHasAlphaChannel(hasAlphaChannel) + mTexture(texture) { #ifdef USE_OPENGL mGLImage = 0; #endif - mUseAlphaCache = Image::mEnableAlphaCache; - mBounds.x = 0; mBounds.y = 0; + mBounds.w = width; + mBounds.h = height; - mLoaded = false; + mLoaded = mTexture != nullptr; - if (mSDLSurface) + if (!mLoaded) { - mBounds.w = mSDLSurface->w; - mBounds.h = mSDLSurface->h; - - mLoaded = true; - } - else logger->log( "Image::Image(SDL_Surface*): Couldn't load invalid Surface!"); + } } #ifdef USE_OPENGL Image::Image(GLuint glimage, int width, int height, int texWidth, int texHeight): mAlpha(1.0f), - mSDLSurface(0), - mAlphaChannel(0), - mHasAlphaChannel(true), - mUseAlphaCache(false), + mTexture(0), mGLImage(glimage), mTexWidth(texWidth), mTexHeight(texHeight) @@ -140,10 +129,8 @@ Resource *Image::load(SDL_RWops *rw, Dye const &dye) rgba.Gmask = 0x00FF0000; rgba.Gloss = 0; rgba.Gshift = 16; rgba.Bmask = 0x0000FF00; rgba.Bloss = 0; rgba.Bshift = 8; rgba.Amask = 0x000000FF; rgba.Aloss = 0; rgba.Ashift = 0; - rgba.colorkey = 0; - rgba.alpha = 255; - SDL_Surface *surf = SDL_ConvertSurface(tmpImage, &rgba, SDL_SWSURFACE); + SDL_Surface *surf = SDL_ConvertSurface(tmpImage, &rgba, 0); SDL_FreeSurface(tmpImage); Uint32 *pixels = static_cast< Uint32 * >(surf->pixels); @@ -173,34 +160,14 @@ Image *Image::load(SDL_Surface *tmpImage) return _SDLload(tmpImage); } -void Image::SDLcleanCache() -{ - ResourceManager *resman = ResourceManager::getInstance(); - - for (std::map<float, SDL_Surface*>::iterator - i = mAlphaCache.begin(), i_end = mAlphaCache.end(); - i != i_end; ++i) - { - if (mSDLSurface != i->second) - resman->scheduleDelete(i->second); - i->second = 0; - } - mAlphaCache.clear(); -} - void Image::unload() { mLoaded = false; - if (mSDLSurface) + if (mTexture) { - SDLcleanCache(); - // Free the image surface. - SDL_FreeSurface(mSDLSurface); - mSDLSurface = NULL; - - delete[] mAlphaChannel; - mAlphaChannel = NULL; + SDL_DestroyTexture(mTexture); + mTexture = NULL; } #ifdef USE_OPENGL @@ -221,27 +188,6 @@ bool Image::useOpenGL() #endif } -bool Image::hasAlphaChannel() -{ - if (!mLoaded) - return false; - -#ifdef USE_OPENGL - if (mUseOpenGL) - return true; -#endif - - return mHasAlphaChannel; -} - -SDL_Surface *Image::getByAlpha(float alpha) -{ - std::map<float, SDL_Surface*>::iterator it = mAlphaCache.find(alpha); - if (it != mAlphaCache.end()) - return (*it).second; - return 0; -} - void Image::setAlpha(float alpha) { if (!useOpenGL() && mDisableTransparency) @@ -253,188 +199,26 @@ void Image::setAlpha(float alpha) if (alpha < 0.0f || alpha > 1.0f) return; - if (mSDLSurface) - { - if (mUseAlphaCache) - { - SDL_Surface *surface = getByAlpha(mAlpha); - if (!surface) - { - if (mAlphaCache.size() > 100) - SDLcleanCache(); - - mAlphaCache[mAlpha] = mSDLSurface; - } - surface = getByAlpha(alpha); - if (surface) - { - mAlphaCache.erase(alpha); - mSDLSurface = surface; - mAlpha = alpha; - return; - } - else - { - mSDLSurface = Image::SDLduplicateSurface(mSDLSurface); - } - } - - mAlpha = alpha; - - if (!hasAlphaChannel()) - { - // 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); - - // Precompute as much as possible - int maxHeight = std::min((mBounds.y + mBounds.h), mSDLSurface->h); - int maxWidth = std::min((mBounds.x + mBounds.w), mSDLSurface->w); - int i = 0; - - for (int y = mBounds.y; y < maxHeight; y++) - for (int x = mBounds.x; x < maxWidth; x++) - { - i = y * mSDLSurface->w + x; - // Only change the pixel if it was visible at load time... - Uint8 sourceAlpha = mAlphaChannel[i]; - if (sourceAlpha > 0) - { - Uint8 r, g, b, a; - SDL_GetRGBA(((Uint32*) mSDLSurface->pixels)[i], - mSDLSurface->format, - &r, &g, &b, &a); - - a = (Uint8) (sourceAlpha * mAlpha); - - // Here is the pixel we want to set - ((Uint32 *)(mSDLSurface->pixels))[i] = - SDL_MapRGBA(mSDLSurface->format, r, g, b, a); - } - } - - if (SDL_MUSTLOCK(mSDLSurface)) - SDL_UnlockSurface(mSDLSurface); - } - } - else - { - mAlpha = alpha; - } -} - -Image *Image::SDLgetScaledImage(int width, int height) -{ - if (width == 0 || height == 0) - return 0; + mAlpha = alpha; - // Increase our reference count and return ourselves in case of same size - if (width == getWidth() && height == getHeight()) + if (mTexture) { - incRef(); - return this; - } - - if (!mSDLSurface) - return 0; - - ResourceManager *resman = ResourceManager::getInstance(); - - // Generate a unique ID path for storing the scaled version in the - // resource manager. - std::string idPath = getIdPath(); - idPath += ":scaled:"; - idPath += toString(width); - idPath += "x"; - idPath += toString(height); - - // Try whether a scaled version is already available - Image *scaledImage = static_cast<Image*>(resman->get(idPath)); - - if (!scaledImage) - { - // No scaled version with this size exists already, so create one - SDL_Surface *scaledSurface = zoomSurface(mSDLSurface, - (double) width / getWidth(), - (double) height / getHeight(), - 1); - - if (scaledSurface) - { - scaledImage = load(scaledSurface); - SDL_FreeSurface(scaledSurface); - - // Place the scaled image in the resource manager - resman->addResource(idPath, scaledImage); - } + SDL_SetTextureAlphaMod(mTexture, (Uint8) (255 * mAlpha)); } - - return scaledImage; } -SDL_Surface* Image::SDLduplicateSurface(SDL_Surface* tmpImage) +Image *Image::_SDLload(SDL_Surface *image) { - if (!tmpImage || !tmpImage->format) + if (!image || !mRenderer) return NULL; - return SDL_ConvertSurface(tmpImage, tmpImage->format, SDL_SWSURFACE); + SDL_Texture *texture = SDL_CreateTextureFromSurface(mRenderer, image); + return new Image(texture, image->w, image->h); } -Image *Image::_SDLload(SDL_Surface *tmpImage) +void Image::setRenderer(SDL_Renderer *renderer) { - if (!tmpImage) - return NULL; - - 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 - for (int i = 0; i < tmpImage->w * tmpImage->h; ++i) - { - Uint8 r, g, b, a; - SDL_GetRGBA( - ((Uint32*) tmpImage->pixels)[i], - tmpImage->format, - &r, &g, &b, &a); - - if (a != 255) - hasAlpha = true; - - alphaChannel[i] = a; - } - } - - SDL_Surface *image; - - // Convert the surface to the current display format - 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, hasAlpha, alphaChannel); + mRenderer = renderer; } #ifdef USE_OPENGL @@ -489,7 +273,7 @@ Image *Image::_GLload(SDL_Surface *image) } // Make sure the alpha channel is not used, but copied to destination - SDL_SetAlpha(oldImage, 0, SDL_ALPHA_OPAQUE); + SDL_SetSurfaceBlendMode(oldImage, SDL_BLENDMODE_NONE); SDL_BlitSurface(oldImage, NULL, image, NULL); } @@ -583,38 +367,24 @@ Image *Image::getSubImage(int x, int y, int width, int height) mTexWidth, mTexHeight); #endif - return new SubImage(this, mSDLSurface, + return new SubImage(this, mTexture, mBounds.x + x, mBounds.y + y, width, height); } -void Image::SDLterminateAlphaCache() -{ - SDLcleanCache(); - mUseAlphaCache = false; -} - //============================================================================ // SubImage Class //============================================================================ -SubImage::SubImage(Image *parent, SDL_Surface *image, +SubImage::SubImage(Image *parent, SDL_Texture *texture, int x, int y, int width, int height): - Image(image), + Image(texture, width, height), mParent(parent) { if (mParent) { mParent->incRef(); - mParent->SDLterminateAlphaCache(); - mHasAlphaChannel = mParent->hasAlphaChannel(); - mAlphaChannel = mParent->SDLgetAlphaChannel(); - } - else - { - mHasAlphaChannel = false; - mAlphaChannel = 0; } // Set up the rectangle. @@ -622,7 +392,6 @@ SubImage::SubImage(Image *parent, SDL_Surface *image, mBounds.y = y; mBounds.w = width; mBounds.h = height; - mUseAlphaCache = false; } #ifdef USE_OPENGL @@ -644,10 +413,8 @@ SubImage::SubImage(Image *parent, GLuint image, SubImage::~SubImage() { - // Avoid destruction of the image - mSDLSurface = 0; - // Avoid possible destruction of its alpha channel - mAlphaChannel = 0; + // Avoid destruction of the texture + mTexture = nullptr; #ifdef USE_OPENGL mGLImage = 0; #endif diff --git a/src/resources/image.h b/src/resources/image.h index b762bf2a..efe2262e 100644 --- a/src/resources/image.h +++ b/src/resources/image.h @@ -37,8 +37,6 @@ #include <SDL_opengl.h> #endif -#include <map> - class Dye; class Position; @@ -129,12 +127,6 @@ class Image : public Resource */ Image *getSubImage(int x, int y, int width, int height); - /** - * Tells if the image has got an alpha channel - * @return true if it's true, false otherwise. - */ - bool hasAlphaChannel(); - // SDL only public functions /** @@ -146,31 +138,7 @@ class Image : public Resource static bool SDLisTransparencyDisabled() { return mDisableTransparency; } - /** - * Gets an scaled instance of an image. The returned image is managed - * by the ResourceManager. - * - * @param width The desired width of the scaled image. - * @param height The desired height of the scaled image. - * - * @return An Image resource, or 0 on failure. - */ - Image *SDLgetScaledImage(int width, int height); - - /** - * Get the alpha Channel of a SDL surface. - */ - Uint8 *SDLgetAlphaChannel() const - { return mAlphaChannel; } - - SDL_Surface* SDLduplicateSurface(SDL_Surface* tmpImage); - - void SDLcleanCache(); - - void SDLterminateAlphaCache(); - - static void SDLsetEnableAlphaCache(bool n) - { mEnableAlphaCache = n; } + static void setRenderer(SDL_Renderer *renderer); #ifdef USE_OPENGL @@ -204,30 +172,18 @@ class Image : public Resource // ----------------------- /** SDL Constructor */ - Image(SDL_Surface *image, bool hasAlphaChannel = false, - Uint8 *alphaChannel = NULL); + Image(SDL_Texture *texture, int width, int height); - /** SDL_Surface to SDL_Surface Image loader */ + /** SDL_Surface to SDL_Texture Image loader */ static Image *_SDLload(SDL_Surface *tmpImage); - SDL_Surface *getByAlpha(float alpha); - - SDL_Surface *mSDLSurface; - - /** Alpha Channel pointer used for 32bit based SDL surfaces */ - Uint8 *mAlphaChannel; - bool mHasAlphaChannel; - - /** Alpha cache: The cache stores a copy of the image - for specific requested opacities, hence, increasing - the image disply speed */ - std::map<float, SDL_Surface*> mAlphaCache; - bool mUseAlphaCache; - static bool mEnableAlphaCache; + SDL_Texture *mTexture; /** Stores whether the transparency is disabled */ static bool mDisableTransparency; + static SDL_Renderer *mRenderer; + // ----------------------- // OpenGL protected members // ----------------------- @@ -261,7 +217,7 @@ class Image : public Resource class SubImage : public Image { public: - SubImage(Image *parent, SDL_Surface *image, + SubImage(Image *parent, SDL_Texture *texture, int x, int y, int width, int height); #ifdef USE_OPENGL SubImage(Image *parent, GLuint image, int x, int y, |