#include #include #include #include #include #include "TextureCache.h" #include "TextureLoader/TextureLoader.h" #include "FileLoader/FileLoader.h" using namespace std; //#define DEBUG_GL_ERROR #ifdef DEBUG_GL_ERROR #define checkGLError() checkGLErrorLine(__FUNCTION__, __LINE__) #else #define checkGLError() #endif static void checkGLErrorLine(const char * function, int line) { GLenum err = glGetError(); if (err != 0) { cerr << "gl error in " << function << ": " << err << " (0x" << hex << err << ") at line " << dec << line << endl; } } TextureCache::~TextureCache() { } GLuint TextureCache::load(const FileLoader::Path & path, FileLoader & fileLoader, bool mipmaps, int mode, int quality) { string filename = path.shortPath; if (filename == "") filename = path.fullPath; if (filename == "") return 0; map::iterator it = m_cache.find(filename); if (it != m_cache.end()) return it->second; GLuint tex = loadTexture(path, fileLoader, mipmaps, mode, quality); m_cache[filename] = tex; return tex; } GLuint TextureCache::loadTexture(const FileLoader::Path & path, FileLoader & fileLoader, bool mipmaps, int mode, int quality) { checkGLError(); GLuint texture; FileLoader::Buffer buff = fileLoader.load(path); if (buff.size <= 0) return 0; SDL_RWops * ops = SDL_RWFromMem(buff.data, buff.size); SDL_Surface * temp = IMG_Load_RW(ops, true); if (!temp) { cerr << "Failed to load image ('" << path.fullPath << "', '" << path.shortPath << "'): " << IMG_GetError() << endl; return 0; } SDL_PixelFormat fmt; fmt.palette = NULL; fmt.BitsPerPixel = 32; fmt.BytesPerPixel = 4; fmt.Rmask = 0x000000FF; fmt.Gmask = 0x0000FF00; fmt.Bmask = 0x00FF0000; fmt.Amask = 0xFF000000; fmt.Rshift = 0; fmt.Gshift = 8; fmt.Bshift = 16; fmt.Ashift = 24; SDL_Surface * texsurf = SDL_ConvertSurface(temp, &fmt, SDL_SWSURFACE); SDL_FreeSurface(temp); if (!texsurf) { cerr << "Image was not converted properly!" << endl; return 0; } unsigned int * pixels = new unsigned int[texsurf->w * texsurf->h]; int y; unsigned int dstOffset = texsurf->w * (texsurf->h - 1); unsigned int srcOffset = 0; for (y = 0; y < texsurf->h; y++) { memcpy(pixels + dstOffset, ((unsigned int *)texsurf->pixels) + srcOffset, texsurf->w << 2); dstOffset -= texsurf->w; srcOffset += texsurf->w; } glGenTextures(1, &texture); checkGLError(); glBindTexture(GL_TEXTURE_2D, texture); checkGLError(); glTexImage2D(GL_TEXTURE_2D, 0, 4, texsurf->w, texsurf->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); if (quality > 0) { checkGLError(); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, mipmaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR); checkGLError(); } else { checkGLError(); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, mipmaps ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST); checkGLError(); } checkGLError(); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode); checkGLError(); if (mipmaps) { checkGLError(); gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, texsurf->w, texsurf->h, GL_RGBA, GL_UNSIGNED_BYTE, pixels); checkGLError(); } SDL_FreeSurface(texsurf); delete[] pixels; checkGLError(); return texture; }