Files
openglplayground/texture.hh

96 lines
2.1 KiB
C++

#ifndef __OPENGLPLAYGROUND_TEXTURE_HH__
#define __OPENGLPLAYGROUND_TEXTURE_HH__
#include <string>
#include <cstdio>
#include <cassert>
#include <algorithm>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
#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