#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; }