diff options
-rw-r--r-- | src/CMakeLists.txt | 4 | ||||
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/client.cpp | 27 | ||||
-rw-r--r-- | src/compoundsprite.cpp | 10 | ||||
-rw-r--r-- | src/graphics.cpp | 17 | ||||
-rw-r--r-- | src/graphicsmanager.cpp | 22 | ||||
-rw-r--r-- | src/gui/debugwindow.cpp | 2 | ||||
-rw-r--r-- | src/gui/minimap.cpp | 2 | ||||
-rw-r--r-- | src/gui/sdlfont.cpp | 2 | ||||
-rw-r--r-- | src/gui/widgets/desktop.cpp | 4 | ||||
-rw-r--r-- | src/opengl1graphics.cpp | 17 | ||||
-rw-r--r-- | src/openglgraphics.cpp | 33 | ||||
-rw-r--r-- | src/resources/ambientlayer.cpp | 4 | ||||
-rw-r--r-- | src/resources/image.cpp | 12 | ||||
-rw-r--r-- | src/resources/image.h | 2 | ||||
-rw-r--r-- | src/resources/imagehelper.cpp | 471 | ||||
-rw-r--r-- | src/resources/imagehelper.h | 107 | ||||
-rw-r--r-- | src/resources/openglimagehelper.cpp | 278 | ||||
-rw-r--r-- | src/resources/openglimagehelper.h | 122 | ||||
-rw-r--r-- | src/resources/resourcemanager.cpp | 4 | ||||
-rw-r--r-- | src/resources/sdlimagehelper.cpp | 280 | ||||
-rw-r--r-- | src/resources/sdlimagehelper.h | 85 |
22 files changed, 879 insertions, 630 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bdca0a37b..4cb8bd869 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -429,10 +429,14 @@ SET(SRCS resources/music.h resources/npcdb.cpp resources/npcdb.h + resources/openglimagehelper.cpp + resources/openglimagehelper.h resources/resource.cpp resources/resource.h resources/resourcemanager.cpp resources/resourcemanager.h + resources/sdlimagehelper.cpp + resources/sdlimagehelper.h resources/soundeffect.h resources/soundeffect.cpp resources/spritedef.h diff --git a/src/Makefile.am b/src/Makefile.am index 38cbeecde..0bf3c056c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -443,10 +443,14 @@ manaplus_SOURCES += gui/widgets/avatarlistbox.cpp \ resources/music.h \ resources/npcdb.cpp \ resources/npcdb.h \ + resources/openglimagehelper.cpp \ + resources/openglimagehelper.h \ resources/resource.cpp \ resources/resource.h \ resources/resourcemanager.cpp \ resources/resourcemanager.h \ + resources/sdlimagehelper.cpp \ + resources/sdlimagehelper.h \ resources/soundeffect.cpp \ resources/soundeffect.h \ resources/spritedef.cpp \ diff --git a/src/client.cpp b/src/client.cpp index 35658f0f9..b782ce3a1 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -86,6 +86,8 @@ #include "resources/emotedb.h" #include "resources/image.h" #include "resources/imagehelper.h" +#include "resources/openglimagehelper.h" +#include "resources/sdlimagehelper.h" #include "resources/itemdb.h" #include "resources/mapdb.h" #include "resources/monsterdb.h" @@ -397,16 +399,6 @@ void Client::gameInit() "Exiting.", mLocalDataDir.c_str())); } -#if defined USE_OPENGL - ImageHelper::setBlur(config.getBoolValue("blur")); - ImageHelper::SDLSetEnableAlphaCache(config.getBoolValue("alphaCache") - && !config.getIntValue("opengl")); - ImageHelper::setEnableAlpha(config.getFloatValue("guialpha") != 1.0f - || config.getIntValue("opengl")); -#else - ImageHelper::SDLSetEnableAlphaCache(config.getBoolValue("alphaCache")); - ImageHelper::setEnableAlpha(config.getFloatValue("guialpha") != 1.0f); -#endif resman->addToSearchPath(PKG_DATADIR "data/perserver/default", false); @@ -518,6 +510,18 @@ void Client::gameInit() config.setValue("videodetected", true); } #endif + +#if defined USE_OPENGL + OpenGLImageHelper::setBlur(config.getBoolValue("blur")); + SDLImageHelper::SDLSetEnableAlphaCache(config.getBoolValue("alphaCache") + && !config.getIntValue("opengl")); + ImageHelper::setEnableAlpha(config.getFloatValue("guialpha") != 1.0f + || config.getIntValue("opengl")); +#else + SDLImageHelper::SDLSetEnableAlphaCache(config.getBoolValue("alphaCache")); + ImageHelper::setEnableAlpha(config.getFloatValue("guialpha") != 1.0f); +#endif + graphicsManager.initGraphics(mOptions.noOpenGL); runCounters = config.getBoolValue("packetcounters"); @@ -716,6 +720,9 @@ void Client::gameClear() delete mainGraphics; mainGraphics = nullptr; + delete imageHelper; + imageHelper = nullptr; + if (logger) logger->log1("Quitting4"); diff --git a/src/compoundsprite.cpp b/src/compoundsprite.cpp index 41a53467e..fe6e6ba2a 100644 --- a/src/compoundsprite.cpp +++ b/src/compoundsprite.cpp @@ -34,6 +34,7 @@ #include "resources/image.h" #include "resources/imagehelper.h" +#include "resources/openglimagehelper.h" #include "utils/dtor.h" @@ -396,12 +397,12 @@ void CompoundSprite::redraw() const delete mImage; delete mAlphaImage; - mImage = ImageHelper::load(surface); + mImage = imageHelper->load(surface); SDL_FreeSurface(surface); if (ImageHelper::mEnableAlpha) { - mAlphaImage = ImageHelper::load(surfaceA); + mAlphaImage = imageHelper->load(surfaceA); SDL_FreeSurface(surfaceA); } else @@ -415,7 +416,8 @@ void CompoundSprite::setAlpha(float alpha) if (alpha != mAlpha) { #ifdef USE_OPENGL - if (mEnableAlphaFix && ImageHelper::mUseOpenGL == 0 && size() > 3) + if (mEnableAlphaFix && imageHelper->useOpenGL() == 0 + && size() > 3) #else if (mEnableAlphaFix && size() > 3) #endif @@ -434,7 +436,7 @@ void CompoundSprite::setAlpha(float alpha) void CompoundSprite::updateImages() const { #ifdef USE_OPENGL - if (ImageHelper::mUseOpenGL) + if (imageHelper->useOpenGL()) return; #endif diff --git a/src/graphics.cpp b/src/graphics.cpp index 02567b5f2..a082c5e4b 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -31,6 +31,7 @@ #include "resources/image.h" #include "resources/imagehelper.h" +#include "resources/openglimagehelper.h" #include "utils/stringutils.h" #include <guichan/sdl/sdlpixel.hpp> @@ -179,24 +180,24 @@ bool Graphics::setOpenGLMode() GLint texSize; bool rectTex = graphicsManager.supportExtension( "GL_ARB_texture_rectangle"); - if (rectTex && ImageHelper::getInternalTextureType() == 4 + if (rectTex && OpenGLImageHelper::getInternalTextureType() == 4 && config.getBoolValue("rectangulartextures")) { logger->log1("using GL_ARB_texture_rectangle"); - ImageHelper::mTextureType = GL_TEXTURE_RECTANGLE_ARB; + OpenGLImageHelper::mTextureType = GL_TEXTURE_RECTANGLE_ARB; glEnable(GL_TEXTURE_RECTANGLE_ARB); glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &texSize); - ImageHelper::mTextureSize = texSize; + OpenGLImageHelper::mTextureSize = texSize; logger->log("OpenGL texture size: %d pixels (rectangle textures)", - ImageHelper::mTextureSize); + OpenGLImageHelper::mTextureSize); } else { - ImageHelper::mTextureType = GL_TEXTURE_2D; + OpenGLImageHelper::mTextureType = GL_TEXTURE_2D; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texSize); - ImageHelper::mTextureSize = texSize; + OpenGLImageHelper::mTextureSize = texSize; logger->log("OpenGL texture size: %d pixels", - ImageHelper::mTextureSize); + OpenGLImageHelper::mTextureSize); } return videoInfo(); #else @@ -284,7 +285,7 @@ bool Graphics::videoInfo() mDoubleBuffer = ((mTarget->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF); logger->log("Double buffer mode: %s", mDoubleBuffer ? "yes" : "no"); - ImageHelper::dumpSurfaceFormat(mTarget); + imageHelper->dumpSurfaceFormat(mTarget); const SDL_VideoInfo *vi = SDL_GetVideoInfo(); if (!vi) diff --git a/src/graphicsmanager.cpp b/src/graphicsmanager.cpp index 61e157353..e32cf24ef 100644 --- a/src/graphicsmanager.cpp +++ b/src/graphicsmanager.cpp @@ -26,6 +26,8 @@ #include "logger.h" #include "resources/imagehelper.h" +#include "resources/openglimagehelper.h" +#include "resources/sdlimagehelper.h" #include "utils/paths.h" #include "utils/stringutils.h" @@ -153,26 +155,30 @@ void GraphicsManager::initGraphics(bool noOpenGL) useOpenGL = config.getIntValue("opengl"); // Setup image loading for the right image format - ImageHelper::setLoadAsOpenGL(useOpenGL); + OpenGLImageHelper::setLoadAsOpenGL(useOpenGL); GraphicsVertexes::setLoadAsOpenGL(useOpenGL); // Create the graphics context switch (useOpenGL) { case 0: + imageHelper = new SDLImageHelper; mainGraphics = new Graphics; break; case 1: default: + imageHelper = new OpenGLImageHelper; mainGraphics = new OpenGLGraphics; break; case 2: + imageHelper = new OpenGLImageHelper; mainGraphics = new OpenGL1Graphics; break; }; #else // Create the graphics context + imageHelper = new SDLImageHelper; mainGraphics = new Graphics; #endif } @@ -210,7 +216,7 @@ void GraphicsManager::updateTextureFormat() if (formats[f] == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) { delete []formats; - ImageHelper::setInternalTextureType( + OpenGLImageHelper::setInternalTextureType( GL_COMPRESSED_RGBA_S3TC_DXT5_EXT); logger->log1("using s3tc texture compression"); return; @@ -218,19 +224,21 @@ void GraphicsManager::updateTextureFormat() else if (formats[f] == GL_COMPRESSED_RGBA_FXT1_3DFX) { delete []formats; - ImageHelper::setInternalTextureType( + OpenGLImageHelper::setInternalTextureType( GL_COMPRESSED_RGBA_FXT1_3DFX); logger->log1("using fxt1 texture compression"); return; } } - ImageHelper::setInternalTextureType(GL_COMPRESSED_RGBA_ARB); + OpenGLImageHelper::setInternalTextureType( + GL_COMPRESSED_RGBA_ARB); logger->log1("using texture compression"); return; } else { - ImageHelper::setInternalTextureType(GL_COMPRESSED_RGBA_ARB); + OpenGLImageHelper::setInternalTextureType( + GL_COMPRESSED_RGBA_ARB); logger->log1("using texture compression"); return; } @@ -240,12 +248,12 @@ void GraphicsManager::updateTextureFormat() // using default formats if (config.getBoolValue("newtextures")) { - ImageHelper::setInternalTextureType(GL_RGBA); + OpenGLImageHelper::setInternalTextureType(GL_RGBA); logger->log1("using RGBA texture format"); } else { - ImageHelper::setInternalTextureType(4); + OpenGLImageHelper::setInternalTextureType(4); logger->log1("using 4 texture format"); } #endif diff --git a/src/gui/debugwindow.cpp b/src/gui/debugwindow.cpp index 6d0895426..6951d5b4f 100644 --- a/src/gui/debugwindow.cpp +++ b/src/gui/debugwindow.cpp @@ -158,7 +158,7 @@ MapDebugTab::MapDebugTab() : mUpdateTime = 0; #ifdef USE_OPENGL - switch (ImageHelper::getLoadAsOpenGL()) + switch (imageHelper->useOpenGL()) { case 0: mFPSText = _("%d FPS (Software)"); diff --git a/src/gui/minimap.cpp b/src/gui/minimap.cpp index 30d9f40bb..651d9a66c 100644 --- a/src/gui/minimap.cpp +++ b/src/gui/minimap.cpp @@ -143,7 +143,7 @@ void Minimap::setMap(Map *map) SDL_UnlockSurface(surface); - mMapImage = ImageHelper::load(surface); + mMapImage = imageHelper->load(surface); mMapImage->setAlpha(Client::getGuiAlpha()); mCustomMapImage = true; SDL_FreeSurface(surface); diff --git a/src/gui/sdlfont.cpp b/src/gui/sdlfont.cpp index bafc2c8e2..b623337eb 100644 --- a/src/gui/sdlfont.cpp +++ b/src/gui/sdlfont.cpp @@ -85,7 +85,7 @@ class SDLTextChunk return; } - img = ImageHelper::createTextSurface(surface, alpha); + img = imageHelper->createTextSurface(surface, alpha); SDL_FreeSurface(surface); } diff --git a/src/gui/widgets/desktop.cpp b/src/gui/widgets/desktop.cpp index a0f2eb3fe..d3a2e8c50 100644 --- a/src/gui/widgets/desktop.cpp +++ b/src/gui/widgets/desktop.cpp @@ -100,7 +100,7 @@ void Desktop::draw(gcn::Graphics *graphics) if (mWallpaper) { - if (!ImageHelper::useOpenGL()) + if (!imageHelper->useOpenGL()) { g->drawImage(mWallpaper, (getWidth() - mWallpaper->getWidth()) / 2, @@ -136,7 +136,7 @@ void Desktop::setBestFittingWallpaper() if (mWallpaper) mWallpaper->decRef(); - if (!ImageHelper::useOpenGL() + if (!imageHelper->useOpenGL() && (nWallPaper->getWidth() != getWidth() || nWallPaper->getHeight() != getHeight())) { diff --git a/src/opengl1graphics.cpp b/src/opengl1graphics.cpp index 2bb6e06a2..be16008dc 100644 --- a/src/opengl1graphics.cpp +++ b/src/opengl1graphics.cpp @@ -31,6 +31,7 @@ #include "resources/image.h" #include "resources/imagehelper.h" +#include "resources/openglimagehelper.h" #include <SDL.h> @@ -67,7 +68,7 @@ static inline void drawQuad(const Image *image, int srcX, int srcY, int dstX, int dstY, int width, int height) { - if (ImageHelper::mTextureType == GL_TEXTURE_2D) + if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D) { // Find OpenGL normalized texture coordinates. float texX1 = static_cast<float>(srcX) @@ -105,7 +106,7 @@ static inline void drawRescaledQuad(Image *image, int srcX, int srcY, int dstX, int dstY, int width, int height, int desiredWidth, int desiredHeight) { - if (ImageHelper::mTextureType == GL_TEXTURE_2D) + if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D) { // Find OpenGL normalized texture coordinates. float texX1 = static_cast<float>(srcX) @@ -153,7 +154,7 @@ bool OpenGL1Graphics::drawImage(const Image *image, int srcX, int srcY, if (!useColor) glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); - bindTexture(ImageHelper::mTextureType, image->mGLImage); + bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage); setTexturingAndBlending(true); @@ -213,7 +214,7 @@ bool OpenGL1Graphics::drawRescaledImage(Image *image, int srcX, int srcY, if (!useColor) glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); - bindTexture(ImageHelper::mTextureType, image->mGLImage); + bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage); setTexturingAndBlending(true); @@ -267,7 +268,7 @@ void OpenGL1Graphics::drawImagePattern(const Image *image, int x, int y, glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); - bindTexture(ImageHelper::mTextureType, image->mGLImage); + bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage); setTexturingAndBlending(true); @@ -313,7 +314,7 @@ void OpenGL1Graphics::drawRescaledImagePattern(Image *image, int x, int y, glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); - bindTexture(ImageHelper::mTextureType, image->mGLImage); + bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage); setTexturingAndBlending(true); @@ -629,7 +630,7 @@ void OpenGL1Graphics::setTexturingAndBlending(bool enable) { if (!mTexture) { - glEnable(ImageHelper::mTextureType); + glEnable(OpenGLImageHelper::mTextureType); mTexture = true; } @@ -655,7 +656,7 @@ void OpenGL1Graphics::setTexturingAndBlending(bool enable) if (mTexture) { - glDisable(ImageHelper::mTextureType); + glDisable(OpenGLImageHelper::mTextureType); mTexture = false; } } diff --git a/src/openglgraphics.cpp b/src/openglgraphics.cpp index 3ca2a8c09..6b89f4bca 100644 --- a/src/openglgraphics.cpp +++ b/src/openglgraphics.cpp @@ -31,6 +31,7 @@ #include "resources/image.h" #include "resources/imagehelper.h" +#include "resources/openglimagehelper.h" #include "utils/stringutils.h" @@ -81,7 +82,7 @@ static inline void drawQuad(const Image *image, int srcX, int srcY, int dstX, int dstY, int width, int height) { - if (ImageHelper::mTextureType == GL_TEXTURE_2D) + if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D) { // Find OpenGL normalized texture coordinates. const float texX1 = static_cast<float>(srcX) / @@ -143,7 +144,7 @@ static inline void drawRescaledQuad(Image *image, int width, int height, int desiredWidth, int desiredHeight) { - if (ImageHelper::mTextureType == GL_TEXTURE_2D) + if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D) { // Find OpenGL normalized texture coordinates. const float texX1 = static_cast<float>(srcX) / @@ -214,7 +215,7 @@ bool OpenGLGraphics::drawImage(const Image *image, int srcX, int srcY, if (!useColor) glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); - bindTexture(ImageHelper::mTextureType, image->mGLImage); + bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage); setTexturingAndBlending(true); @@ -271,7 +272,7 @@ bool OpenGLGraphics::drawRescaledImage(Image *image, int srcX, int srcY, if (!useColor) glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); - bindTexture(ImageHelper::mTextureType, image->mGLImage); + bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage); setTexturingAndBlending(true); @@ -324,14 +325,14 @@ void OpenGLGraphics::drawImagePattern(const Image *image, int x, int y, glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); - bindTexture(ImageHelper::mTextureType, image->mGLImage); + bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage); setTexturingAndBlending(true); unsigned int vp = 0; const unsigned int vLimit = vertexBufSize * 4; // Draw a set of textured rectangles - if (ImageHelper::mTextureType == GL_TEXTURE_2D) + if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D) { float texX1 = static_cast<float>(srcX) / tw; float texY1 = static_cast<float>(srcY) / th; @@ -458,7 +459,7 @@ void OpenGLGraphics::drawRescaledImagePattern(Image *image, glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); - bindTexture(ImageHelper::mTextureType, image->mGLImage); + bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage); setTexturingAndBlending(true); @@ -466,7 +467,7 @@ void OpenGLGraphics::drawRescaledImagePattern(Image *image, const unsigned int vLimit = vertexBufSize * 4; // Draw a set of textured rectangles - if (ImageHelper::mTextureType == GL_TEXTURE_2D) + if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D) { const float tw = static_cast<float>(image->getTextureWidth()); const float th = static_cast<float>(image->getTextureHeight()); @@ -598,7 +599,7 @@ void OpenGLGraphics::drawImagePattern2(GraphicsVertexes *vert, OpenGLGraphicsVertexes *ogl = vert->getOGL(); glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); - bindTexture(ImageHelper::mTextureType, image->mGLImage); + bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage); setTexturingAndBlending(true); std::vector<GLint*> *intVertPool = ogl->getIntVertPool(); @@ -609,7 +610,7 @@ void OpenGLGraphics::drawImagePattern2(GraphicsVertexes *vert, std::vector<int>::const_iterator ivp_end = vp->end(); // Draw a set of textured rectangles - if (ImageHelper::mTextureType == GL_TEXTURE_2D) + if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D) { std::vector<GLfloat*> *floatTexPool = ogl->getFloatTexPool(); std::vector<GLfloat*>::const_iterator ft; @@ -678,7 +679,7 @@ void OpenGLGraphics::calcImagePattern(GraphicsVertexes* vert, Image *image, ogl->init(); // Draw a set of textured rectangles - if (ImageHelper::mTextureType == GL_TEXTURE_2D) + if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D) { float texX1 = static_cast<float>(srcX) / tw; float texY1 = static_cast<float>(srcY) / th; @@ -811,7 +812,7 @@ void OpenGLGraphics::calcTile(ImageVertexes *vert, int dstX, int dstY) unsigned int vp = ogl->ptr; // Draw a set of textured rectangles - if (ImageHelper::mTextureType == GL_TEXTURE_2D) + if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D) { float texX1 = static_cast<float>(srcX) / tw; float texY1 = static_cast<float>(srcY) / th; @@ -912,10 +913,10 @@ void OpenGLGraphics::drawTile(ImageVertexes *vert) OpenGLGraphicsVertexes *ogl = vert->ogl; glColor4f(1.0f, 1.0f, 1.0f, image->mAlpha); - bindTexture(ImageHelper::mTextureType, image->mGLImage); + bindTexture(OpenGLImageHelper::mTextureType, image->mGLImage); setTexturingAndBlending(true); - if (ImageHelper::mTextureType == GL_TEXTURE_2D) + if (OpenGLImageHelper::mTextureType == GL_TEXTURE_2D) drawQuadArrayfi(ogl->mIntVertArray, ogl->mFloatTexArray, ogl->ptr); else drawQuadArrayii(ogl->mIntVertArray, ogl->mIntTexArray, ogl->ptr); @@ -1189,7 +1190,7 @@ void OpenGLGraphics::setTexturingAndBlending(bool enable) { if (!mTexture) { - glEnable(ImageHelper::mTextureType); + glEnable(OpenGLImageHelper::mTextureType); mTexture = true; } @@ -1215,7 +1216,7 @@ void OpenGLGraphics::setTexturingAndBlending(bool enable) if (mTexture) { - glDisable(ImageHelper::mTextureType); + glDisable(OpenGLImageHelper::mTextureType); mTexture = false; } } diff --git a/src/resources/ambientlayer.cpp b/src/resources/ambientlayer.cpp index f2eaeab81..e51160efe 100644 --- a/src/resources/ambientlayer.cpp +++ b/src/resources/ambientlayer.cpp @@ -39,7 +39,7 @@ AmbientLayer::AmbientLayer(Image *img, float parallax, if (!mImage) return; - if (keepRatio && !ImageHelper::useOpenGL() + if (keepRatio && !imageHelper->useOpenGL() /*&& defaultScreenWidth != 0 && defaultScreenHeight != 0*/ && mainGraphics->mWidth != defaultScreenWidth @@ -106,7 +106,7 @@ void AmbientLayer::draw(Graphics *graphics, int x, int y) if (!mImage) return; - if (!ImageHelper::useOpenGL() || !mKeepRatio) + if (!imageHelper->useOpenGL() || !mKeepRatio) { graphics->drawImagePattern(mImage, static_cast<int>(-mPosX), static_cast<int>(-mPosY), x + static_cast<int>(mPosX), diff --git a/src/resources/image.cpp b/src/resources/image.cpp index 5496a10d8..b060be6f4 100644 --- a/src/resources/image.cpp +++ b/src/resources/image.cpp @@ -37,6 +37,8 @@ #include "utils/stringutils.h" #include "resources/imagehelper.h" +#include "resources/openglimagehelper.h" +#include "resources/sdlimagehelper.h" #include "resources/subimage.h" #include <SDL_image.h> @@ -56,7 +58,7 @@ Image::Image(SDL_Surface *image, bool hasAlphaChannel0, Uint8 *alphaChannel): mGLImage = 0; #endif - mUseAlphaCache = ImageHelper::mEnableAlphaCache; + mUseAlphaCache = SDLImageHelper::mEnableAlphaCache; mBounds.x = 0; mBounds.y = 0; @@ -165,7 +167,7 @@ bool Image::hasAlphaChannel() return mHasAlphaChannel; #ifdef USE_OPENGL - if (ImageHelper::mUseOpenGL) + if (OpenGLImageHelper::mUseOpenGL) return true; #endif @@ -232,7 +234,7 @@ void Image::setAlpha(float alpha) } else { - mSDLSurface = ImageHelper::SDLDuplicateSurface(mSDLSurface); + mSDLSurface = SDLImageHelper::SDLDuplicateSurface(mSDLSurface); } // logger->log("miss"); } @@ -310,7 +312,7 @@ Image* Image::SDLgetScaledImage(int width, int height) // and about freeing the given SDL_surface*. if (scaledSurface) { - scaledImage = ImageHelper::load(scaledSurface); + scaledImage = imageHelper->load(scaledSurface); SDL_FreeSurface(scaledSurface); } } @@ -321,7 +323,7 @@ Image *Image::getSubImage(int x, int y, int width, int height) { // Create a new clipped sub-image #ifdef USE_OPENGL - if (ImageHelper::mUseOpenGL) + if (OpenGLImageHelper::mUseOpenGL) { return new SubImage(this, mGLImage, x, y, width, height, mTexWidth, mTexHeight); diff --git a/src/resources/image.h b/src/resources/image.h index 4bee1f0ed..c7d2657bd 100644 --- a/src/resources/image.h +++ b/src/resources/image.h @@ -56,6 +56,8 @@ class Image : public Resource friend class CompoundSprite; friend class Graphics; friend class ImageHelper; + friend class OpenGLImageHelper; + friend class SDLImageHelper; #ifdef USE_OPENGL friend class OpenGLGraphics; friend class OpenGL1Graphics; diff --git a/src/resources/imagehelper.cpp b/src/resources/imagehelper.cpp index 9ee52267e..a70889acd 100644 --- a/src/resources/imagehelper.cpp +++ b/src/resources/imagehelper.cpp @@ -25,11 +25,6 @@ #include "resources/dye.h" #include "resources/resourcemanager.h" -#ifdef USE_OPENGL -#include "openglgraphics.h" -#include "opengl1graphics.h" -#endif - #include "client.h" #include "logger.h" #include "main.h" @@ -43,14 +38,8 @@ #include "debug.h" -#ifdef USE_OPENGL -int ImageHelper::mUseOpenGL = 0; -int ImageHelper::mTextureType = 0; -int ImageHelper::mInternalTextureType = GL_RGBA8; -int ImageHelper::mTextureSize = 0; -bool ImageHelper::mBlur = true; -#endif -bool ImageHelper::mEnableAlphaCache = false; +ImageHelper *imageHelper = nullptr; + bool ImageHelper::mEnableAlpha = true; Resource *ImageHelper::load(SDL_RWops *rw) @@ -69,198 +58,6 @@ Resource *ImageHelper::load(SDL_RWops *rw) return image; } -Resource *ImageHelper::load(SDL_RWops *rw, Dye const &dye) -{ - SDL_Surface *tmpImage = IMG_Load_RW(rw, 1); - - if (!tmpImage) - { - logger->log("Error, image load failed: %s", IMG_GetError()); - return nullptr; - } - - SDL_Surface *surf = nullptr; - SDL_PixelFormat rgba; - rgba.palette = nullptr; - rgba.BitsPerPixel = 32; - rgba.BytesPerPixel = 4; - rgba.colorkey = 0; - rgba.alpha = 255; - if (mUseOpenGL) - { - surf = convertTo32Bit(tmpImage); - SDL_FreeSurface(tmpImage); - - Uint32 *pixels = static_cast<Uint32 *>(surf->pixels); - DyePalette *pal = dye.getSPalete(); - - if (pal) - { - for (Uint32 *p_end = pixels + surf->w * surf->h; - pixels != p_end; ++pixels) - { - Uint8 *p = (Uint8 *)pixels; - const int alpha = *p & 255; - if (!alpha) - continue; - pal->replaceOGLColor(p); - } - } - else - { - for (Uint32 *p_end = pixels + surf->w * surf->h; - pixels != p_end; ++pixels) - { - const Uint32 p = *pixels; - const int alpha = (p >> 24) & 255; - if (!alpha) - continue; - int v[3]; - v[0] = (p) & 255; - v[1] = (p >> 8) & 255; - v[2] = (p >> 16 ) & 255; - dye.update(v); - *pixels = (v[0]) | (v[1] << 8) | (v[2] << 16) | (alpha << 24); - } - } - } - else - { - rgba.Rmask = 0xFF000000; rgba.Rloss = 0; rgba.Rshift = 24; - 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; - - surf = SDL_ConvertSurface(tmpImage, &rgba, SDL_SWSURFACE); - SDL_FreeSurface(tmpImage); - - Uint32 *pixels = static_cast<Uint32 *>(surf->pixels); - DyePalette *pal = dye.getSPalete(); - - if (pal) - { - for (Uint32 *p_end = pixels + surf->w * surf->h; - pixels != p_end; ++pixels) - { - Uint8 *p = (Uint8 *)pixels; - const int alpha = *p & 255; - if (!alpha) - continue; - pal->replaceColor(p + 1); - } - } - else - { - for (Uint32 *p_end = pixels + surf->w * surf->h; - pixels != p_end; ++pixels) - { - const Uint32 p = *pixels; - const int alpha = p & 255; - if (!alpha) - continue; - int v[3]; - v[0] = (p >> 24) & 255; - v[1] = (p >> 16) & 255; - v[2] = (p >> 8 ) & 255; - dye.update(v); - *pixels = (v[0] << 24) | (v[1] << 16) | (v[2] << 8) | alpha; - } - } - } - - Image *image = load(surf); - SDL_FreeSurface(surf); - return image; -} - -Image *ImageHelper::load(SDL_Surface *tmpImage) -{ -#ifdef USE_OPENGL - if (mUseOpenGL) - return _GLload(tmpImage); -#endif - return _SDLload(tmpImage); -} - -Image *ImageHelper::createTextSurface(SDL_Surface *tmpImage, float alpha) -{ - if (!tmpImage) - return nullptr; - - Image *img; -#ifdef USE_OPENGL - if (mUseOpenGL) - { - img = _GLload(tmpImage); - if (img) - img->setAlpha(alpha); - return img; - } -#endif - - bool hasAlpha = false; - bool converted = false; - - const int sz = tmpImage->w * tmpImage->h; - - // The alpha channel to be filled with alpha values - Uint8 *alphaChannel = new Uint8[sz]; - - const SDL_PixelFormat * const fmt = tmpImage->format; - if (fmt->Amask) - { - for (int i = 0; i < sz; ++ i) - { - Uint32 c = (static_cast<Uint32*>(tmpImage->pixels))[i]; - - unsigned v = (c & fmt->Amask) >> fmt->Ashift; - Uint8 a = (v << fmt->Aloss) + (v >> (8 - (fmt->Aloss << 1))); - - Uint8 a2 = static_cast<Uint8>(static_cast<float>(a) * alpha); - - c &= ~fmt->Amask; - c |= ((a2 >> fmt->Aloss) << fmt->Ashift & fmt->Amask); - (static_cast<Uint32*>(tmpImage->pixels))[i] = c; - - 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 = nullptr; - } - - if (!image) - { - logger->log1("Error: Image convert failed."); - delete [] alphaChannel; - return nullptr; - } - - if (converted) - SDL_FreeSurface(tmpImage); - - img = new Image(image, hasAlpha, alphaChannel); - img->mAlpha = alpha; - return img; -} - SDL_Surface* ImageHelper::convertTo32Bit(SDL_Surface* tmpImage) { if (!tmpImage) @@ -301,261 +98,6 @@ SDL_Surface* ImageHelper::convertTo32Bit(SDL_Surface* tmpImage) return SDL_ConvertSurface(tmpImage, &RGBAFormat, SDL_SWSURFACE); } -SDL_Surface* ImageHelper::SDLDuplicateSurface(SDL_Surface* tmpImage) -{ - if (!tmpImage || !tmpImage->format) - return nullptr; - - return SDL_ConvertSurface(tmpImage, tmpImage->format, SDL_SWSURFACE); -} - -Image *ImageHelper::_SDLload(SDL_Surface *tmpImage) -{ - if (!tmpImage) - return nullptr; - - bool hasAlpha = false; - bool converted = false; - - if (tmpImage->format->BitsPerPixel != 32) - { - tmpImage = convertTo32Bit(tmpImage); - - if (!tmpImage) - return nullptr; - converted = true; - } - - const int sz = tmpImage->w * tmpImage->h; - - // The alpha channel to be filled with alpha values - Uint8 *alphaChannel = new Uint8[sz]; - - // Figure out whether the image uses its alpha layer - if (!tmpImage->format->palette) - { - const SDL_PixelFormat * const fmt = tmpImage->format; - if (fmt->Amask) - { - for (int i = 0; i < sz; ++ i) - { - unsigned v = ((static_cast<Uint32*>(tmpImage->pixels))[i] - & fmt->Amask) >> fmt->Ashift; - Uint8 a = (v << fmt->Aloss) + (v >> (8 - (fmt->Aloss << 1))); - - if (a != 255) - hasAlpha = true; - - alphaChannel[i] = a; - } - } - else - { - if (SDL_ALPHA_OPAQUE != 255) - { - hasAlpha = true; - memset(alphaChannel, SDL_ALPHA_OPAQUE, sz); - } - } - } - else - { - if (SDL_ALPHA_OPAQUE != 255) - { - hasAlpha = true; - memset(alphaChannel, SDL_ALPHA_OPAQUE, sz); - } - } - - 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 = nullptr; - } - - if (!image) - { - logger->log1("Error: Image convert failed."); - delete [] alphaChannel; - return nullptr; - } - - if (converted) - SDL_FreeSurface(tmpImage); - - return new Image(image, hasAlpha, alphaChannel); -} - -#ifdef USE_OPENGL -int ImageHelper::powerOfTwo(int input) -{ - int value; - if (mTextureType == GL_TEXTURE_2D) - { - value = 1; - while (value < input && value < mTextureSize) - value <<= 1; - } - else - { - value = input; - } - return value >= mTextureSize ? mTextureSize : value; -} - -Image *ImageHelper::_GLload(SDL_Surface *tmpImage) -{ - if (!tmpImage) - return nullptr; - - // Flush current error flag. - glGetError(); - - int width = tmpImage->w; - int height = tmpImage->h; - int realWidth = powerOfTwo(width); - int realHeight = powerOfTwo(height); - - if (realWidth < width || realHeight < height) - { - logger->log("Warning: image too large, cropping to %dx%d texture!", - tmpImage->w, tmpImage->h); - } - - // Make sure the alpha channel is not used, but copied to destination - SDL_SetAlpha(tmpImage, 0, SDL_ALPHA_OPAQUE); - - // Determine 32-bit masks based on byte order - Uint32 rmask, gmask, bmask, amask; -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - rmask = 0xff000000; - gmask = 0x00ff0000; - bmask = 0x0000ff00; - amask = 0x000000ff; -#else - rmask = 0x000000ff; - gmask = 0x0000ff00; - bmask = 0x00ff0000; - amask = 0xff000000; -#endif - - SDL_Surface *oldImage = nullptr; - if (tmpImage->format->BitsPerPixel != 32 - || realWidth != width || realHeight != height - || rmask != tmpImage->format->Rmask - || gmask != tmpImage->format->Gmask - || amask != tmpImage->format->Amask) - { - oldImage = tmpImage; - tmpImage = SDL_CreateRGBSurface(SDL_SWSURFACE, realWidth, realHeight, - 32, rmask, gmask, bmask, amask); - - if (!tmpImage) - { - logger->log("Error, image convert failed: out of memory"); - return nullptr; - } - SDL_BlitSurface(oldImage, nullptr, tmpImage, nullptr); - } - - GLuint texture; - glGenTextures(1, &texture); - if (mUseOpenGL == 1) - OpenGLGraphics::bindTexture(mTextureType, texture); - else if (mUseOpenGL == 2) - OpenGL1Graphics::bindTexture(mTextureType, texture); - - if (SDL_MUSTLOCK(tmpImage)) - SDL_LockSurface(tmpImage); - - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - if (mBlur) - { - glTexParameteri(mTextureType, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(mTextureType, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - else - { - glTexParameteri(mTextureType, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(mTextureType, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - } - - glTexImage2D(mTextureType, 0, mInternalTextureType, - tmpImage->w, tmpImage->h, - 0, GL_RGBA, GL_UNSIGNED_BYTE, tmpImage->pixels); - -/* - GLint compressed; - glGetTexLevelParameteriv(mTextureType, 0, - GL_TEXTURE_COMPRESSED_ARB, &compressed); - if (compressed) - logger->log("image compressed"); - else - logger->log("image not compressed"); -*/ - -#ifdef DEBUG_OPENGL_LEAKS - textures_count ++; -#endif - - if (SDL_MUSTLOCK(tmpImage)) - SDL_UnlockSurface(tmpImage); - - if (oldImage) - SDL_FreeSurface(tmpImage); - - GLenum error = glGetError(); - if (error) - { - std::string errmsg = "Unknown error"; - switch (error) - { - case GL_INVALID_ENUM: - errmsg = "GL_INVALID_ENUM"; - break; - case GL_INVALID_VALUE: - errmsg = "GL_INVALID_VALUE"; - break; - case GL_INVALID_OPERATION: - errmsg = "GL_INVALID_OPERATION"; - break; - case GL_STACK_OVERFLOW: - errmsg = "GL_STACK_OVERFLOW"; - break; - case GL_STACK_UNDERFLOW: - errmsg = "GL_STACK_UNDERFLOW"; - break; - case GL_OUT_OF_MEMORY: - errmsg = "GL_OUT_OF_MEMORY"; - break; - default: - break; - } - logger->log("Error: Image GL import failed: %s", errmsg.c_str()); - return nullptr; - } - - return new Image(texture, width, height, realWidth, realHeight); -} - -void ImageHelper::setLoadAsOpenGL(int useOpenGL) -{ - ImageHelper::mUseOpenGL = useOpenGL; -} - -#endif - void ImageHelper::dumpSurfaceFormat(SDL_Surface *image) { if (image->format) @@ -571,12 +113,3 @@ void ImageHelper::dumpSurfaceFormat(SDL_Surface *image) format->Gmask, format->Bmask, format->Amask); } } - -int ImageHelper::useOpenGL() -{ -#ifdef USE_OPENGL - return mUseOpenGL; -#else - return 0; -#endif -} diff --git a/src/resources/imagehelper.h b/src/resources/imagehelper.h index 680794625..b0cbca7e6 100644 --- a/src/resources/imagehelper.h +++ b/src/resources/imagehelper.h @@ -24,26 +24,11 @@ #define IMAGEHELPER_H #include "localconsts.h" -#include "main.h" #include "resources/resource.h" #include <SDL.h> -#ifdef USE_OPENGL - -/* The definition of OpenGL extensions by SDL is giving problems with recent - * gl.h headers, since they also include these definitions. As we're not using - * extensions anyway it's safe to just disable the SDL version. - */ -//#define NO_SDL_GLEXT -#define GL_GLEXT_PROTOTYPES 1 - -#include <SDL_opengl.h> -#endif - -#include <map> - class Dye; class Image; @@ -52,17 +37,12 @@ struct Position; /** * Defines a class for loading and storing images. */ -class ImageHelper : public Resource +class ImageHelper { - friend class CompoundSprite; - friend class Graphics; - friend class Image; -#ifdef USE_OPENGL - friend class OpenGLGraphics; - friend class OpenGL1Graphics; -#endif - public: + virtual ~ImageHelper() + { } + /** * Loads an image from an SDL_RWops structure. * @@ -71,7 +51,7 @@ class ImageHelper : public Resource * @return <code>NULL</code> if an error occurred, a valid pointer * otherwise. */ - static Resource *load(SDL_RWops *rw); + Resource *load(SDL_RWops *rw); /** * Loads an image from an SDL_RWops structure and recolors it. @@ -82,89 +62,28 @@ class ImageHelper : public Resource * @return <code>NULL</code> if an error occurred, a valid pointer * otherwise. */ - static Resource *load(SDL_RWops *rw, Dye const &dye); + virtual Resource *load(SDL_RWops *rw, Dye const &dye) = 0; /** * Loads an image from an SDL surface. */ - static Image *load(SDL_Surface *); + virtual Image *load(SDL_Surface *) = 0; - static SDL_Surface *convertTo32Bit(SDL_Surface* tmpImage); + virtual Image *createTextSurface(SDL_Surface *tmpImage, + float alpha) = 0; - static Image *createTextSurface(SDL_Surface *tmpImage, float alpha); + virtual int useOpenGL() = 0; - static void SDLSetEnableAlphaCache(bool n) - { mEnableAlphaCache = n; } + SDL_Surface *convertTo32Bit(SDL_Surface* tmpImage); - static bool SDLGetEnableAlphaCache() - { return mEnableAlphaCache; } + void dumpSurfaceFormat(SDL_Surface *image); static void setEnableAlpha(bool n) { mEnableAlpha = n; } -#ifdef USE_OPENGL - - // OpenGL only public functions - - /** - * Sets the target image format. Use <code>false</code> for SDL and - * <code>true</code> for OpenGL. - */ - static void setLoadAsOpenGL(int useOpenGL); - - static int getLoadAsOpenGL() - { return mUseOpenGL; } - - static int getTextureType() - { return mTextureType; } - - static int getInternalTextureType() - { return mInternalTextureType; } - - static void setInternalTextureType(int n) - { mInternalTextureType = n; } - - static void setBlur(bool n) - { mBlur = n; } - - static int mTextureType; - - static int mInternalTextureType; - - static void dumpSurfaceFormat(SDL_Surface *image); - - static SDL_Surface* SDLDuplicateSurface(SDL_Surface* tmpImage); - -#endif - - /** - * Tells if the image was loaded using OpenGL or SDL - * @return true if OpenGL, false if SDL. - */ - static int useOpenGL(); - protected: - /** SDL_Surface to SDL_Surface Image loader */ - static Image *_SDLload(SDL_Surface *tmpImage); - - static bool mEnableAlphaCache; static bool mEnableAlpha; - - // ----------------------- - // OpenGL protected members - // ----------------------- -#ifdef USE_OPENGL - /** - * Returns the first power of two equal or bigger than the input. - */ - static int powerOfTwo(int input); - - static Image *_GLload(SDL_Surface *tmpImage); - - static int mUseOpenGL; - static int mTextureSize; - static bool mBlur; -#endif }; +extern ImageHelper *imageHelper; #endif diff --git a/src/resources/openglimagehelper.cpp b/src/resources/openglimagehelper.cpp new file mode 100644 index 000000000..1de5305c4 --- /dev/null +++ b/src/resources/openglimagehelper.cpp @@ -0,0 +1,278 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2012 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "resources/openglimagehelper.h" + +#ifdef USE_OPENGL + +#include "resources/dye.h" +#include "resources/resourcemanager.h" + +#include "openglgraphics.h" +#include "opengl1graphics.h" + +#include "client.h" +#include "logger.h" + +#include "utils/stringutils.h" + +#include "resources/image.h" + +#include <SDL_image.h> +#include <SDL_rotozoom.h> + +#include "debug.h" + +int OpenGLImageHelper::mTextureType = 0; +int OpenGLImageHelper::mInternalTextureType = GL_RGBA8; +int OpenGLImageHelper::mTextureSize = 0; +bool OpenGLImageHelper::mBlur = true; +int OpenGLImageHelper::mUseOpenGL = 0; + +Resource *OpenGLImageHelper::load(SDL_RWops *rw, Dye const &dye) +{ + SDL_Surface *tmpImage = IMG_Load_RW(rw, 1); + + if (!tmpImage) + { + logger->log("Error, image load failed: %s", IMG_GetError()); + return nullptr; + } + + SDL_Surface *surf = convertTo32Bit(tmpImage); + SDL_FreeSurface(tmpImage); + + Uint32 *pixels = static_cast<Uint32 *>(surf->pixels); + DyePalette *pal = dye.getSPalete(); + + if (pal) + { + for (Uint32 *p_end = pixels + surf->w * surf->h; + pixels != p_end; ++pixels) + { + Uint8 *p = (Uint8 *)pixels; + const int alpha = *p & 255; + if (!alpha) + continue; + pal->replaceOGLColor(p); + } + } + else + { + for (Uint32 *p_end = pixels + surf->w * surf->h; + pixels != p_end; ++pixels) + { + const Uint32 p = *pixels; + const int alpha = (p >> 24) & 255; + if (!alpha) + continue; + int v[3]; + v[0] = (p) & 255; + v[1] = (p >> 8) & 255; + v[2] = (p >> 16 ) & 255; + dye.update(v); + *pixels = (v[0]) | (v[1] << 8) | (v[2] << 16) | (alpha << 24); + } + } + + Image *image = load(surf); + SDL_FreeSurface(surf); + return image; +} + +Image *OpenGLImageHelper::load(SDL_Surface *tmpImage) +{ + return _GLload(tmpImage); +} + +Image *OpenGLImageHelper::createTextSurface(SDL_Surface *tmpImage, float alpha) +{ + if (!tmpImage) + return nullptr; + + Image *img = _GLload(tmpImage); + if (img) + img->setAlpha(alpha); + return img; +} + +int OpenGLImageHelper::powerOfTwo(int input) +{ + int value; + if (mTextureType == GL_TEXTURE_2D) + { + value = 1; + while (value < input && value < mTextureSize) + value <<= 1; + } + else + { + value = input; + } + return value >= mTextureSize ? mTextureSize : value; +} + +Image *OpenGLImageHelper::_GLload(SDL_Surface *tmpImage) +{ + if (!tmpImage) + return nullptr; + + // Flush current error flag. + glGetError(); + + int width = tmpImage->w; + int height = tmpImage->h; + int realWidth = powerOfTwo(width); + int realHeight = powerOfTwo(height); + + if (realWidth < width || realHeight < height) + { + logger->log("Warning: image too large, cropping to %dx%d texture!", + tmpImage->w, tmpImage->h); + } + + // Make sure the alpha channel is not used, but copied to destination + SDL_SetAlpha(tmpImage, 0, SDL_ALPHA_OPAQUE); + + // Determine 32-bit masks based on byte order + Uint32 rmask, gmask, bmask, amask; +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + rmask = 0xff000000; + gmask = 0x00ff0000; + bmask = 0x0000ff00; + amask = 0x000000ff; +#else + rmask = 0x000000ff; + gmask = 0x0000ff00; + bmask = 0x00ff0000; + amask = 0xff000000; +#endif + + SDL_Surface *oldImage = nullptr; + if (tmpImage->format->BitsPerPixel != 32 + || realWidth != width || realHeight != height + || rmask != tmpImage->format->Rmask + || gmask != tmpImage->format->Gmask + || amask != tmpImage->format->Amask) + { + oldImage = tmpImage; + tmpImage = SDL_CreateRGBSurface(SDL_SWSURFACE, realWidth, realHeight, + 32, rmask, gmask, bmask, amask); + + if (!tmpImage) + { + logger->log("Error, image convert failed: out of memory"); + return nullptr; + } + SDL_BlitSurface(oldImage, nullptr, tmpImage, nullptr); + } + + GLuint texture; + glGenTextures(1, &texture); + if (mUseOpenGL == 1) + OpenGLGraphics::bindTexture(mTextureType, texture); + else if (mUseOpenGL == 2) + OpenGL1Graphics::bindTexture(mTextureType, texture); + + if (SDL_MUSTLOCK(tmpImage)) + SDL_LockSurface(tmpImage); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + if (mBlur) + { + glTexParameteri(mTextureType, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(mTextureType, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + else + { + glTexParameteri(mTextureType, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(mTextureType, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + + glTexImage2D(mTextureType, 0, mInternalTextureType, + tmpImage->w, tmpImage->h, + 0, GL_RGBA, GL_UNSIGNED_BYTE, tmpImage->pixels); + +/* + GLint compressed; + glGetTexLevelParameteriv(mTextureType, 0, + GL_TEXTURE_COMPRESSED_ARB, &compressed); + if (compressed) + logger->log("image compressed"); + else + logger->log("image not compressed"); +*/ + +#ifdef DEBUG_OPENGL_LEAKS + textures_count ++; +#endif + + if (SDL_MUSTLOCK(tmpImage)) + SDL_UnlockSurface(tmpImage); + + if (oldImage) + SDL_FreeSurface(tmpImage); + + GLenum error = glGetError(); + if (error) + { + std::string errmsg = "Unknown error"; + switch (error) + { + case GL_INVALID_ENUM: + errmsg = "GL_INVALID_ENUM"; + break; + case GL_INVALID_VALUE: + errmsg = "GL_INVALID_VALUE"; + break; + case GL_INVALID_OPERATION: + errmsg = "GL_INVALID_OPERATION"; + break; + case GL_STACK_OVERFLOW: + errmsg = "GL_STACK_OVERFLOW"; + break; + case GL_STACK_UNDERFLOW: + errmsg = "GL_STACK_UNDERFLOW"; + break; + case GL_OUT_OF_MEMORY: + errmsg = "GL_OUT_OF_MEMORY"; + break; + default: + break; + } + logger->log("Error: Image GL import failed: %s", errmsg.c_str()); + return nullptr; + } + + return new Image(texture, width, height, realWidth, realHeight); +} + +void OpenGLImageHelper::setLoadAsOpenGL(int useOpenGL) +{ + OpenGLImageHelper::mUseOpenGL = useOpenGL; +} + +int OpenGLImageHelper::useOpenGL() +{ + return mUseOpenGL; +} +#endif diff --git a/src/resources/openglimagehelper.h b/src/resources/openglimagehelper.h new file mode 100644 index 000000000..b27409040 --- /dev/null +++ b/src/resources/openglimagehelper.h @@ -0,0 +1,122 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2012 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef OPENGLIMAGEHELPER_H +#define OPENGLIMAGEHELPER_H + +#include "localconsts.h" +#include "main.h" + +#include "resources/imagehelper.h" + +#include <SDL.h> + +#ifdef USE_OPENGL + +/* The definition of OpenGL extensions by SDL is giving problems with recent + * gl.h headers, since they also include these definitions. As we're not using + * extensions anyway it's safe to just disable the SDL version. + */ +//#define NO_SDL_GLEXT +#define GL_GLEXT_PROTOTYPES 1 + +#include <SDL_opengl.h> +#endif + +class Dye; +class Image; + +/** + * Defines a class for loading and storing images. + */ +class OpenGLImageHelper : public ImageHelper +{ + friend class CompoundSprite; + friend class Graphics; + friend class Image; + + public: + virtual ~OpenGLImageHelper() + { } + + /** + * Loads an image from an SDL_RWops structure and recolors it. + * + * @param rw The SDL_RWops to load the image from. + * @param dye The dye used to recolor the image. + * + * @return <code>NULL</code> if an error occurred, a valid pointer + * otherwise. + */ + Resource *load(SDL_RWops *rw, Dye const &dye); + + /** + * Loads an image from an SDL surface. + */ + Image *load(SDL_Surface *); + + Image *createTextSurface(SDL_Surface *tmpImage, float alpha); + + // OpenGL only public functions + + /** + * Sets the target image format. Use <code>false</code> for SDL and + * <code>true</code> for OpenGL. + */ + static void setLoadAsOpenGL(int useOpenGL); + + static int getTextureType() + { return mTextureType; } + + static int getInternalTextureType() + { return mInternalTextureType; } + + static void setInternalTextureType(int n) + { mInternalTextureType = n; } + + static void setBlur(bool n) + { mBlur = n; } + + static int mTextureType; + + static int mInternalTextureType; + + /** + * Tells if the image was loaded using OpenGL or SDL + * @return true if OpenGL, false if SDL. + */ + int useOpenGL(); + + protected: + /** + * Returns the first power of two equal or bigger than the input. + */ + int powerOfTwo(int input); + + Image *_GLload(SDL_Surface *tmpImage); + + static int mUseOpenGL; + static int mTextureSize; + static bool mBlur; +}; + +#endif diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp index 62a604ebe..37975cf16 100644 --- a/src/resources/resourcemanager.cpp +++ b/src/resources/resourcemanager.cpp @@ -457,8 +457,8 @@ struct DyedImageLoader delete d; return nullptr; } - Resource *res = d ? ImageHelper::load(rw, *d) - : ImageHelper::load(rw); + Resource *res = d ? imageHelper->load(rw, *d) + : imageHelper->load(rw); delete d; return res; } diff --git a/src/resources/sdlimagehelper.cpp b/src/resources/sdlimagehelper.cpp new file mode 100644 index 000000000..66e1bc823 --- /dev/null +++ b/src/resources/sdlimagehelper.cpp @@ -0,0 +1,280 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2012 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "resources/sdlimagehelper.h" + +#include "resources/dye.h" +#include "resources/resourcemanager.h" + +#include "client.h" +#include "logger.h" +#include "main.h" + +#include "utils/stringutils.h" + +#include "resources/image.h" + +#include <SDL_image.h> +#include <SDL_rotozoom.h> + +#include "debug.h" + +bool SDLImageHelper::mEnableAlphaCache = false; + +Resource *SDLImageHelper::load(SDL_RWops *rw, Dye const &dye) +{ + SDL_Surface *tmpImage = IMG_Load_RW(rw, 1); + + if (!tmpImage) + { + logger->log("Error, image load failed: %s", IMG_GetError()); + return nullptr; + } + + SDL_Surface *surf = nullptr; + SDL_PixelFormat rgba; + rgba.palette = nullptr; + rgba.BitsPerPixel = 32; + rgba.BytesPerPixel = 4; + rgba.colorkey = 0; + rgba.alpha = 255; + rgba.Rmask = 0xFF000000; rgba.Rloss = 0; rgba.Rshift = 24; + 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; + + surf = SDL_ConvertSurface(tmpImage, &rgba, SDL_SWSURFACE); + SDL_FreeSurface(tmpImage); + + Uint32 *pixels = static_cast<Uint32 *>(surf->pixels); + DyePalette *pal = dye.getSPalete(); + + if (pal) + { + for (Uint32 *p_end = pixels + surf->w * surf->h; + pixels != p_end; ++pixels) + { + Uint8 *p = (Uint8 *)pixels; + const int alpha = *p & 255; + if (!alpha) + continue; + pal->replaceColor(p + 1); + } + } + else + { + for (Uint32 *p_end = pixels + surf->w * surf->h; + pixels != p_end; ++pixels) + { + const Uint32 p = *pixels; + const int alpha = p & 255; + if (!alpha) + continue; + int v[3]; + v[0] = (p >> 24) & 255; + v[1] = (p >> 16) & 255; + v[2] = (p >> 8 ) & 255; + dye.update(v); + *pixels = (v[0] << 24) | (v[1] << 16) | (v[2] << 8) | alpha; + } + } + + Image *image = load(surf); + SDL_FreeSurface(surf); + return image; +} + +Image *SDLImageHelper::load(SDL_Surface *tmpImage) +{ + return _SDLload(tmpImage); +} + +Image *SDLImageHelper::createTextSurface(SDL_Surface *tmpImage, float alpha) +{ + if (!tmpImage) + return nullptr; + + Image *img; + + bool hasAlpha = false; + bool converted = false; + + const int sz = tmpImage->w * tmpImage->h; + + // The alpha channel to be filled with alpha values + Uint8 *alphaChannel = new Uint8[sz]; + + const SDL_PixelFormat * const fmt = tmpImage->format; + if (fmt->Amask) + { + for (int i = 0; i < sz; ++ i) + { + Uint32 c = (static_cast<Uint32*>(tmpImage->pixels))[i]; + + unsigned v = (c & fmt->Amask) >> fmt->Ashift; + Uint8 a = (v << fmt->Aloss) + (v >> (8 - (fmt->Aloss << 1))); + + Uint8 a2 = static_cast<Uint8>(static_cast<float>(a) * alpha); + + c &= ~fmt->Amask; + c |= ((a2 >> fmt->Aloss) << fmt->Ashift & fmt->Amask); + (static_cast<Uint32*>(tmpImage->pixels))[i] = c; + + 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 = nullptr; + } + + if (!image) + { + logger->log1("Error: Image convert failed."); + delete [] alphaChannel; + return nullptr; + } + + if (converted) + SDL_FreeSurface(tmpImage); + + img = new Image(image, hasAlpha, alphaChannel); + img->mAlpha = alpha; + return img; +} + +SDL_Surface* SDLImageHelper::SDLDuplicateSurface(SDL_Surface* tmpImage) +{ + if (!tmpImage || !tmpImage->format) + return nullptr; + + return SDL_ConvertSurface(tmpImage, tmpImage->format, SDL_SWSURFACE); +} + +Image *SDLImageHelper::_SDLload(SDL_Surface *tmpImage) +{ + if (!tmpImage) + return nullptr; + + bool hasAlpha = false; + bool converted = false; + + if (tmpImage->format->BitsPerPixel != 32) + { + tmpImage = convertTo32Bit(tmpImage); + + if (!tmpImage) + return nullptr; + converted = true; + } + + const int sz = tmpImage->w * tmpImage->h; + + // The alpha channel to be filled with alpha values + Uint8 *alphaChannel = new Uint8[sz]; + + // Figure out whether the image uses its alpha layer + if (!tmpImage->format->palette) + { + const SDL_PixelFormat * const fmt = tmpImage->format; + if (fmt->Amask) + { + for (int i = 0; i < sz; ++ i) + { + unsigned v = ((static_cast<Uint32*>(tmpImage->pixels))[i] + & fmt->Amask) >> fmt->Ashift; + Uint8 a = (v << fmt->Aloss) + (v >> (8 - (fmt->Aloss << 1))); + + if (a != 255) + hasAlpha = true; + + alphaChannel[i] = a; + } + } + else + { + if (SDL_ALPHA_OPAQUE != 255) + { + hasAlpha = true; + memset(alphaChannel, SDL_ALPHA_OPAQUE, sz); + } + } + } + else + { + if (SDL_ALPHA_OPAQUE != 255) + { + hasAlpha = true; + memset(alphaChannel, SDL_ALPHA_OPAQUE, sz); + } + } + + 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 = nullptr; + } + + if (!image) + { + logger->log1("Error: Image convert failed."); + delete [] alphaChannel; + return nullptr; + } + + if (converted) + SDL_FreeSurface(tmpImage); + + return new Image(image, hasAlpha, alphaChannel); +} + +int SDLImageHelper::useOpenGL() +{ + return 0; +} diff --git a/src/resources/sdlimagehelper.h b/src/resources/sdlimagehelper.h new file mode 100644 index 000000000..cecbf6c93 --- /dev/null +++ b/src/resources/sdlimagehelper.h @@ -0,0 +1,85 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2012 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef SDLIMAGEHELPER_H +#define SDLIMAGEHELPER_H + +#include "localconsts.h" + +#include "resources/imagehelper.h" + +#include <SDL.h> + +class Dye; +class Image; + +/** + * Defines a class for loading and storing images. + */ +class SDLImageHelper : public ImageHelper +{ + friend class Image; + + public: + virtual ~SDLImageHelper() + { } + + /** + * Loads an image from an SDL_RWops structure and recolors it. + * + * @param rw The SDL_RWops to load the image from. + * @param dye The dye used to recolor the image. + * + * @return <code>NULL</code> if an error occurred, a valid pointer + * otherwise. + */ + Resource *load(SDL_RWops *rw, Dye const &dye); + + /** + * Loads an image from an SDL surface. + */ + Image *load(SDL_Surface *); + + Image *createTextSurface(SDL_Surface *tmpImage, float alpha); + + static void SDLSetEnableAlphaCache(bool n) + { mEnableAlphaCache = n; } + + static bool SDLGetEnableAlphaCache() + { return mEnableAlphaCache; } + + /** + * Tells if the image was loaded using OpenGL or SDL + * @return true if OpenGL, false if SDL. + */ + int useOpenGL(); + + static SDL_Surface* SDLDuplicateSurface(SDL_Surface* tmpImage); + + protected: + /** SDL_Surface to SDL_Surface Image loader */ + Image *_SDLload(SDL_Surface *tmpImage); + + static bool mEnableAlphaCache; +}; + +#endif |