107 lines
3.4 KiB
C++
107 lines
3.4 KiB
C++
#include "Texture.hpp"
|
|
#include "Log.hpp"
|
|
#include "SDL_image.h"
|
|
|
|
/* ======== Constructors/Destructor ======== */
|
|
Texture::Texture(std::string name_, const char *buffer, size_t buffer_size) {
|
|
name.assign(name_);
|
|
texture = 0;
|
|
flags = 0;
|
|
w = h = 0;
|
|
image = NULL;
|
|
loadImg(buffer, buffer_size);
|
|
}
|
|
// NOTE: this is a special test constructor just so I can use RenderView(s) within the current system nicely
|
|
Texture::Texture(std::string name_, RenderView *view) {
|
|
name.assign(name_);
|
|
texture = view->getTex();
|
|
flags = 0;
|
|
w = view->getWidth();
|
|
h = view->getHeight();
|
|
}
|
|
Texture::~Texture() {
|
|
destroyTexture();
|
|
}
|
|
/* ======== Image/Surface loading/unloading ======== */
|
|
/* loadImg
|
|
This function takes in the given buffer that is composed of an SDL2_image compatible format, copies it to an SDL_RWops, loads it is an SDL_Surface, and then generates an OpenGL texture.
|
|
|
|
Yes, this is wasteful.
|
|
*/
|
|
int Texture::loadImg(const char *buffer, size_t buffer_size) {
|
|
if (flags & LOADED) {
|
|
LOG(LOG_WARNING) << FUNC_NAME << ": surface already loaded - unloading and replacing";
|
|
unloadImg();
|
|
}
|
|
if ((image = IMG_Load_RW(SDL_RWFromMem((char*)buffer, buffer_size), 1)) == NULL) {
|
|
LOG(LOG_ERROR) << FUNC_NAME << ": Could not load image from buffer: " << IMG_GetError();
|
|
return 1;
|
|
}
|
|
flags |= LOADED;
|
|
w = image->w;
|
|
h = image->h;
|
|
return 0;
|
|
}
|
|
/* unloadImg
|
|
This function effectively frees the SDL_Surface allocated by loadImg. It should be called after buildTexture()
|
|
*/
|
|
int Texture::unloadImg() {
|
|
if (flags & LOADED) {
|
|
SDL_FreeSurface(image);
|
|
flags &= ~LOADED;
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
/* ======== Texture generation/destruction ======== */
|
|
/* buildTexture
|
|
This function generates the OpenGL texture is an image is loaded. If the texture is already built, it is destroyed and recreated.
|
|
|
|
Returns 0 if no image is loaded, otherwise it returns the texture ID.
|
|
*/
|
|
GLuint Texture::buildTexture() {
|
|
if (!(flags & LOADED)) {
|
|
LOG(LOG_WARNING) << FUNC_NAME << ": image is not loaded!";
|
|
return 0;
|
|
}
|
|
if (flags & BUILT) {
|
|
LOG(LOG_WARNING) << FUNC_NAME << ": texture already built, destroying and recreating";
|
|
destroyTexture();
|
|
}
|
|
// Unbind any previous texture
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
// Create the texture
|
|
glGenTextures(1, &texture);
|
|
glBindTexture(GL_TEXTURE_2D, texture);
|
|
if (glIsTexture(texture) != 1) {
|
|
LOG(LOG_WARNING) << FUNC_NAME << ": failed to generate texture!";
|
|
return 0;
|
|
}
|
|
#ifdef __APPLE__
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image->w, image->h, 0, GL_BGRA, GL_UNSIGNED_BYTE, image->pixels);
|
|
#else
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image->w, image->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);
|
|
#endif
|
|
/*glGenerateMipmap(GL_TEXTURE_2D);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);*/
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
flags |= BUILT;
|
|
LOG(LOG_DEBUG) << FUNC_NAME << ": " << name << " built as " << texture;
|
|
return texture;
|
|
}
|
|
/* destroyTexture
|
|
Deletes the given texture from OpenGL if it was already built via buildTexture.
|
|
*/
|
|
int Texture::destroyTexture() {
|
|
if (flags & BUILT) {
|
|
glDeleteTextures(1, &texture);
|
|
flags &= ~BUILT;
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|