96 lines
2.1 KiB
C++
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
|