#ifndef __OPENGLPLAYGROUND_TEXTURE_HH__ #define __OPENGLPLAYGROUND_TEXTURE_HH__ #include #include #include #include #include #include #define GL_GLEXT_PROTOTYPES #include #include "common.hh" static unsigned ilog2(unsigned in) { unsigned ret = 0u; while (in >>= 1) ++ret; return ret; } class Texture2D { public: Texture2D(unsigned width, unsigned height) { _glCreate(width, height); } Texture2D(std::string const& file) { SDL_Surface *surf = IMG_Load(file.c_str()); if (!surf) throw SDLException(); try { _glCreate(surf->w, surf->h); try { assert(surf->format->format == SDL_PIXELFORMAT_RGB24); // TODO: Proper support of many formats if (SDL_MUSTLOCK(surf)) SDL_LockSurface(surf); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, surf->w, surf->h, GL_RGB, GL_UNSIGNED_BYTE, surf->pixels); glGenerateMipmap(GL_TEXTURE_2D); checkGlError(); } catch(...) { glDeleteTextures(1, &_texID); throw; } } catch(...) { SDL_FreeSurface(surf); throw; } SDL_FreeSurface(surf); } ~Texture2D() { glDeleteTextures(1, &_texID); } void bind() { glBindTexture(GL_TEXTURE_2D, _texID); checkGlError(); } private: void _glCreate(unsigned width, unsigned height) { glGenTextures(1, &_texID); checkGlError(); try { glBindTexture(GL_TEXTURE_2D, _texID); unsigned logWidth = ilog2(width), logHeight = ilog2(height); unsigned levels = std::max(logWidth,logHeight)+1u; if(SDL_GL_ExtensionSupported("GL_ARB_texture_storage")) glTexStorage2D(GL_TEXTURE_2D, levels, GL_RGB8, width, height); else { std::printf("Warning: extension GL_ARB_texture_storage not supported!\n"); for (unsigned i = 0u; i < levels; ++i) { glTexImage2D(GL_TEXTURE_2D, i, GL_RGB8, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); width = std::max(1u, (width / 2u)); height = std::max(1u, (height / 2u)); } } checkGlError(); } catch(...) { glDeleteTextures(1, &_texID); } } GLuint _texID; }; #endif