X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fvideo%2Ftexture_manager.cpp;h=70b0e950c1522e60cba59f6eddf602e28a383253;hb=43db9a6c44b6ee544e7694d1bb234ba559b0849c;hp=ab5788eaa5e2c1c145c79e31c46564d63afd61a3;hpb=86181b0a14d89cf45daf97199c3556c4dd1ee7b7;p=supertux.git diff --git a/src/video/texture_manager.cpp b/src/video/texture_manager.cpp index ab5788eaa..70b0e950c 100644 --- a/src/video/texture_manager.cpp +++ b/src/video/texture_manager.cpp @@ -1,3 +1,22 @@ +// $Id$ +// +// SuperTux +// Copyright (C) 2006 Matthias Braun +// +// 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 (at your option) 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, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + #include #include "texture_manager.hpp" @@ -5,13 +24,17 @@ #include #include #include -#include #include #include #include #include "physfs/physfs_sdl.hpp" -#include "image_texture.hpp" +#include "video_systems.hpp" +#include "gl_texture.hpp" #include "glutil.hpp" +#include "gameconfig.hpp" +#include "file_system.hpp" +#include "log.hpp" +#include "texture.hpp" TextureManager* texture_manager = NULL; @@ -25,19 +48,18 @@ TextureManager::~TextureManager() i != image_textures.end(); ++i) { if(i->second == NULL) continue; -#ifdef DEBUG - std::cerr << "Warning: Texture '" << i->first << "' not freed\n"; -#endif + log_warning << "Texture '" << i->first << "' not freed" << std::endl; delete i->second; } } -ImageTexture* -TextureManager::get(const std::string& filename) +Texture* +TextureManager::get(const std::string& _filename) { + std::string filename = FileSystem::normalize(_filename); ImageTextures::iterator i = image_textures.find(filename); - ImageTexture* texture = NULL; + Texture* texture = NULL; if(i != image_textures.end()) texture = i->second; @@ -50,101 +72,126 @@ TextureManager::get(const std::string& filename) } void -TextureManager::release(ImageTexture* texture) +TextureManager::release(Texture* texture) { - image_textures[texture->filename] = NULL; + image_textures.erase(texture->get_filename()); delete texture; } +#ifdef HAVE_OPENGL void -TextureManager::register_texture(Texture* texture) +TextureManager::register_texture(GL::Texture* texture) { textures.insert(texture); } void -TextureManager::remove_texture(Texture* texture) +TextureManager::remove_texture(GL::Texture* texture) { textures.erase(texture); } +#endif -static inline int next_power_of_two(int val) -{ - int result = 1; - while(result < val) - result *= 2; - return result; -} - -ImageTexture* +Texture* TextureManager::create_image_texture(const std::string& filename) { - SDL_Surface* image = IMG_Load_RW(get_physfs_SDLRWops(filename), 1); - if(image == NULL) { - std::ostringstream msg; - msg << "Couldn't load image '" << filename << "' :" << SDL_GetError(); - throw std::runtime_error(msg.str()); - } + try { - int texture_w = next_power_of_two(image->w); - int texture_h = next_power_of_two(image->h); - -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - SDL_Surface* convert = SDL_CreateRGBSurface(SDL_SWSURFACE, - texture_w, texture_h, 32, - 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff); -#else - SDL_Surface* convert = SDL_CreateRGBSurface(SDL_SWSURFACE, - texture_w, texture_h, 32, - 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000); -#endif + SDL_Surface* image = IMG_Load_RW(get_physfs_SDLRWops(filename), 1); + if(image == 0) { + std::ostringstream msg; + msg << "Couldn't load image '" << filename << "' :" << SDL_GetError(); + throw std::runtime_error(msg.str()); + } - if(convert == 0) - throw std::runtime_error("Couldn't create texture: out of memory"); + Texture* result = 0; + try { + result = new_texture(image); + result->set_filename(filename); + } catch(...) { + delete result; + SDL_FreeSurface(image); + throw; + } - SDL_SetAlpha(image, 0, 0); - SDL_BlitSurface(image, 0, convert, 0); + SDL_FreeSurface(image); + return result; - ImageTexture* result = NULL; - try { - result = new ImageTexture(convert); - result->filename = filename; - result->image_width = image->w; - result->image_height = image->h; - } catch(...) { - delete result; - SDL_FreeSurface(convert); - throw; + } catch (const std::runtime_error& err) { + const std::string dummy_texture_fname = "images/engine/missing.png"; + if (filename == dummy_texture_fname) throw err; + + // on error, try loading placeholder file + try { + + Texture* tex = create_image_texture(dummy_texture_fname); + log_warning << "Couldn't load texture '" << filename << "' (now using dummy texture): " << err.what() << std::endl; + return tex; + + } catch (...) { + + // on error (when loading placeholder), try using empty surface + try { + + SDL_Surface* image = SDL_CreateRGBSurface(0, 1024, 1024, 8, 0, 0, 0, 0); + if(image == 0) { + throw err; + } + + Texture* result = 0; + try { + result = new_texture(image); + result->set_filename("-dummy-texture-.png"); + } catch(...) { + delete result; + SDL_FreeSurface(image); + throw err; + } + + SDL_FreeSurface(image); + log_warning << "Couldn't load texture '" << filename << "' (now using empty one): " << err.what() << std::endl; + return result; + + // on error (when trying to use empty surface), give up + } catch (const std::runtime_error& err) { + throw err; + } + } } - - SDL_FreeSurface(convert); - return result; } +#ifdef HAVE_OPENGL void TextureManager::save_textures() { +#ifdef GL_PACK_ROW_LENGTH + /* all this stuff is not support by OpenGL ES */ glPixelStorei(GL_PACK_ROW_LENGTH, 0); glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0); glPixelStorei(GL_PACK_SKIP_PIXELS, 0); glPixelStorei(GL_PACK_SKIP_ROWS, 0); glPixelStorei(GL_PACK_SKIP_IMAGES, 0); +#endif + glPixelStorei(GL_PACK_ALIGNMENT, 1); for(Textures::iterator i = textures.begin(); i != textures.end(); ++i) { save_texture(*i); } for(ImageTextures::iterator i = image_textures.begin(); i != image_textures.end(); ++i) { - save_texture(i->second); + save_texture(dynamic_cast(i->second)); } } void -TextureManager::save_texture(Texture* texture) +TextureManager::save_texture(GL::Texture* texture) { SavedTexture saved_texture; saved_texture.texture = texture; glBindTexture(GL_TEXTURE_2D, texture->get_handle()); + + //this doesn't work with OpenGL ES (but we don't need it on the GP2X anyway) +#ifndef GL_VERSION_ES_CM_1_0 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &saved_texture.width); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, @@ -162,32 +209,36 @@ TextureManager::save_texture(Texture* texture) size_t pixelssize = saved_texture.width * saved_texture.height * 4; saved_texture.pixels = new char[pixelssize]; - + glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, saved_texture.pixels); +#endif saved_textures.push_back(saved_texture); - glDeleteTextures(1, &(texture->handle)); - texture->handle = 0; + glDeleteTextures(1, &(texture->get_handle())); + texture->set_handle(0); - assert_gl("retrieving texture"); + assert_gl("retrieving texture for save"); } void TextureManager::reload_textures() { +#ifdef GL_UNPACK_ROW_LENGTH + /* OpenGL ES doesn't support these */ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0); glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0); +#endif glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - + for(std::vector::iterator i = saved_textures.begin(); i != saved_textures.end(); ++i) { SavedTexture& saved_texture = *i; - + GLuint handle; glGenTextures(1, &handle); assert_gl("creating texture handle"); @@ -210,9 +261,9 @@ TextureManager::reload_textures() saved_texture.wrap_t); assert_gl("setting texture_params"); - saved_texture.texture->handle = handle; + saved_texture.texture->set_handle(handle); } saved_textures.clear(); } - +#endif