From 14c82e5b5d5547bcf9c3b06c68cf20a100600d0b Mon Sep 17 00:00:00 2001 From: Guillaume Melquiond Date: Sat, 25 Aug 2007 16:56:52 +0000 Subject: Removed dependency on Guichan's OpenGL library. Taken over image loading and handling. Reduced memory usage when using OpenGL. (Up to 95% reduction for some textures.) --- src/resources/image.cpp | 66 +++++++++++++++-------- src/resources/image.h | 7 +++ src/resources/imageloader.cpp | 99 ++++++++++++++++++++++++++++++++++ src/resources/imageloader.h | 69 ++++++++++++++++++++++++ src/resources/openglsdlimageloader.cpp | 41 -------------- src/resources/openglsdlimageloader.h | 38 ------------- src/resources/sdlimageloader.cpp | 34 ------------ src/resources/sdlimageloader.h | 37 ------------- 8 files changed, 218 insertions(+), 173 deletions(-) create mode 100644 src/resources/imageloader.cpp create mode 100644 src/resources/imageloader.h delete mode 100644 src/resources/openglsdlimageloader.cpp delete mode 100644 src/resources/openglsdlimageloader.h delete mode 100644 src/resources/sdlimageloader.cpp delete mode 100644 src/resources/sdlimageloader.h (limited to 'src/resources') diff --git a/src/resources/image.cpp b/src/resources/image.cpp index ad280eeb..995e34b0 100644 --- a/src/resources/image.cpp +++ b/src/resources/image.cpp @@ -29,6 +29,8 @@ #ifdef USE_OPENGL bool Image::mUseOpenGL = false; +int Image::mTextureType = 0; +int Image::mTextureSize = 0; #endif Image::Image(const std::string &idPath, SDL_Surface *image): @@ -89,23 +91,21 @@ Image* Image::load(void *buffer, unsigned int bufferSize, return NULL; } - // 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 + Image *image = load(tmpImage, idPath); + + SDL_FreeSurface(tmpImage); + return image; +} + +Image *Image::load(SDL_Surface *tmpImage, std::string const &idPath) +{ #ifdef USE_OPENGL if (mUseOpenGL) { + // Flush current error flag. + glGetError(); + int width = tmpImage->w; int height = tmpImage->h; int realWidth = powerOfTwo(width); @@ -120,6 +120,20 @@ Image* Image::load(void *buffer, unsigned int bufferSize, // 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 = tmpImage; tmpImage = SDL_CreateRGBSurface(SDL_SWSURFACE, realWidth, realHeight, 32, rmask, gmask, bmask, amask); @@ -130,25 +144,24 @@ Image* Image::load(void *buffer, unsigned int bufferSize, } SDL_BlitSurface(oldImage, NULL, tmpImage, NULL); - SDL_FreeSurface(oldImage); GLuint texture; glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); + glBindTexture(mTextureType, texture); if (SDL_MUSTLOCK(tmpImage)) { SDL_LockSurface(tmpImage); } glTexImage2D( - GL_TEXTURE_2D, 0, 4, + mTextureType, 0, 4, tmpImage->w, tmpImage->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, tmpImage->pixels); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(mTextureType, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(mTextureType, GL_TEXTURE_MAG_FILTER, GL_NEAREST); if (SDL_MUSTLOCK(tmpImage)) { SDL_UnlockSurface(tmpImage); @@ -219,7 +232,6 @@ Image* Image::load(void *buffer, unsigned int bufferSize, else { image = SDL_DisplayFormat(tmpImage); } - SDL_FreeSurface(tmpImage); if (!image) { logger->log("Error: Image convert failed."); @@ -289,12 +301,20 @@ Image::setLoadAsOpenGL(bool useOpenGL) int Image::powerOfTwo(int input) { - int value = 1; - while (value < input && value < 1024) + int value; + if (mTextureType == GL_TEXTURE_2D) + { + value = 1; + while (value < input && value < mTextureSize) + { + value <<= 1; + } + } + else { - value <<= 1; + value = input; } - return value; + return value >= mTextureSize ? mTextureSize : value; } #endif diff --git a/src/resources/image.h b/src/resources/image.h index cad21dcd..34515dda 100644 --- a/src/resources/image.h +++ b/src/resources/image.h @@ -70,6 +70,11 @@ class Image : public Resource static Image* load(void* buffer, unsigned int bufferSize, const std::string &idPath); + /** + * Loads an image from an SDL surface. + */ + static Image *load(SDL_Surface *, std::string const &idPath); + /** * Frees the resources created by SDL. */ @@ -143,6 +148,8 @@ class Image : public Resource int mTexWidth, mTexHeight; static bool mUseOpenGL; + static int mTextureType; + static int mTextureSize; #endif SDL_Surface *mImage; float mAlpha; diff --git a/src/resources/imageloader.cpp b/src/resources/imageloader.cpp new file mode 100644 index 00000000..b2053dcc --- /dev/null +++ b/src/resources/imageloader.cpp @@ -0,0 +1,99 @@ +/* + * The Mana World + * Copyright 2007 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#include +#include +#include +#include + +#include "imageloader.h" + +#include "image.h" +#include "resourcemanager.h" + +ProxyImage::ProxyImage(SDL_Surface *s): + mImage(NULL), mSDLImage(s) +{ +} + +ProxyImage::~ProxyImage() +{ + free(); +} + +void ProxyImage::free() +{ + if (mSDLImage) + { + SDL_FreeSurface(mSDLImage); + mSDLImage = NULL; + } + else if (mImage) + { + delete mImage; + mImage = NULL; + } +} + +int ProxyImage::getWidth() const +{ + return mSDLImage ? mSDLImage->w : mImage->getWidth(); +} + +int ProxyImage::getHeight() const +{ + return mSDLImage ? mSDLImage->h : mImage->getHeight(); +} + +gcn::Color ProxyImage::getPixel(int x, int y) +{ + assert(mSDLImage); + return gcn::SDLgetPixel(mSDLImage, x, y); +} + +void ProxyImage::putPixel(int x, int y, gcn::Color const &color) +{ + assert(mSDLImage); + gcn::SDLputPixel(mSDLImage, x, y, color); +} + +void ProxyImage::convertToDisplayFormat() +{ + assert(mSDLImage); + /* The picture is most probably full of the pink pixels Guichan uses for + transparency, as this function will only be called when setting an image + font. Get rid of them. */ + SDL_SetColorKey(mSDLImage, SDL_SRCCOLORKEY, + SDL_MapRGB(mSDLImage->format, 255, 0, 255)); + mImage = ::Image::load(mSDLImage, std::string()); + SDL_FreeSurface(mSDLImage); + mSDLImage = NULL; +} + +gcn::Image *ImageLoader::load(std::string const &filename, bool convert) +{ + ResourceManager *resman = ResourceManager::getInstance(); + ProxyImage *i = new ProxyImage(resman->loadSDLSurface(filename)); + if (convert) i->convertToDisplayFormat(); + return i; +} diff --git a/src/resources/imageloader.h b/src/resources/imageloader.h new file mode 100644 index 00000000..f41f6472 --- /dev/null +++ b/src/resources/imageloader.h @@ -0,0 +1,69 @@ +/* + * The Mana World + * Copyright 2007 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World 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. + * + * The Mana World 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 The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#ifndef _TMW_IMAGELOADER_H +#define _TMW_IMAGELOADER_H + +#include + +#include +#include + +class Image; +struct SDL_Surface; + +class ProxyImage : public gcn::Image +{ + public: + ProxyImage(SDL_Surface *); + ~ProxyImage(); + void free(); + int getWidth() const; + int getHeight() const; + gcn::Color getPixel(int x, int y); + void putPixel(int x, int y, gcn::Color const &color); + void convertToDisplayFormat(); + + /** + * Gets the image handled by this proxy. + */ + ::Image *getImage() const + { return mImage; } + + private: + ::Image *mImage; /**< The real image. */ + + /** + * An SDL surface kept around until Guichan is done reading pixels from + * an OpenGL texture. + */ + SDL_Surface *mSDLImage; +}; + +class ImageLoader : public gcn::ImageLoader +{ + public: + gcn::Image *load(std::string const &filename, bool convertToDisplayFormat); +}; + +#endif diff --git a/src/resources/openglsdlimageloader.cpp b/src/resources/openglsdlimageloader.cpp deleted file mode 100644 index 9b6645bd..00000000 --- a/src/resources/openglsdlimageloader.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * The Mana World - * Copyright 2004 The Mana World Development Team - * - * This file is part of The Mana World. - * - * The Mana World 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. - * - * The Mana World 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 The Mana World; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - */ - -#include "openglsdlimageloader.h" - -#include - -#include "resourcemanager.h" - -#include "../main.h" - -#ifdef USE_OPENGL - -SDL_Surface* -OpenGLSDLImageLoader::loadSDLSurface(const std::string &filename) -{ - ResourceManager *resman = ResourceManager::getInstance(); - return resman->loadSDLSurface(filename); -} - -#endif diff --git a/src/resources/openglsdlimageloader.h b/src/resources/openglsdlimageloader.h deleted file mode 100644 index d776dafe..00000000 --- a/src/resources/openglsdlimageloader.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * The Mana World - * Copyright 2004 The Mana World Development Team - * - * This file is part of The Mana World. - * - * The Mana World 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. - * - * The Mana World 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 The Mana World; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - */ - -#ifndef _TMW_OPENGLSDLIMAGELOADER_H -#define _TMW_OPENGLSDLIMAGELOADER_H - -#include - -#include - -class OpenGLSDLImageLoader : public gcn::OpenGLSDLImageLoader -{ - protected: - SDL_Surface* - loadSDLSurface(const std::string &filename); -}; - -#endif diff --git a/src/resources/sdlimageloader.cpp b/src/resources/sdlimageloader.cpp deleted file mode 100644 index ae4f4dcb..00000000 --- a/src/resources/sdlimageloader.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * The Mana World - * Copyright 2004 The Mana World Development Team - * - * This file is part of The Mana World. - * - * The Mana World 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. - * - * The Mana World 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 The Mana World; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - */ - -#include "sdlimageloader.h" - -#include - -#include "resourcemanager.h" - -SDL_Surface* SDLImageLoader::loadSDLSurface(const std::string& filename) -{ - ResourceManager *resman = ResourceManager::getInstance(); - return resman->loadSDLSurface(filename); -} diff --git a/src/resources/sdlimageloader.h b/src/resources/sdlimageloader.h deleted file mode 100644 index 50b1d4f1..00000000 --- a/src/resources/sdlimageloader.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * The Mana World - * Copyright 2004 The Mana World Development Team - * - * This file is part of The Mana World. - * - * The Mana World 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. - * - * The Mana World 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 The Mana World; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - */ - -#ifndef _TMW_SDLIMAGELOADER_H -#define _TMW_SDLIMAGELOADER_H - -#include - -#include - -class SDLImageLoader : public gcn::SDLImageLoader -{ - protected: - SDL_Surface* loadSDLSurface(const std::string& filename); -}; - -#endif -- cgit v1.2.3-70-g09d2