fix: OpenGL textures not being cleaned up correctly

This commit is contained in:
WerWolv
2022-09-18 20:38:45 +02:00
parent 5eabc05396
commit 3cdc8c5884
8 changed files with 115 additions and 112 deletions

View File

@@ -31,27 +31,40 @@ enum ImGuiCustomCol {
namespace ImGui {
struct Texture {
ImTextureID textureId = nullptr;
int width = 0, height = 0;
class Texture {
public:
Texture() = default;
Texture(const ImU8 *buffer, int size);
Texture(const char *path);
Texture(const Texture&) = delete;
Texture(Texture&& other) noexcept;
[[nodiscard]] constexpr bool valid() const noexcept {
return this->textureId != nullptr;
~Texture();
void operator=(const Texture&) = delete;
void operator=(Texture&& other) noexcept;
[[nodiscard]] constexpr bool isValid() const noexcept {
return this->m_textureId != nullptr;
}
[[nodiscard]] constexpr operator ImTextureID() {
return this->textureId;
return this->m_textureId;
}
[[nodiscard]] auto size() const noexcept {
return ImVec2(this->width, this->height);
[[nodiscard]] auto getSize() const noexcept {
return ImVec2(this->m_width, this->m_height);
}
[[nodiscard]] constexpr auto aspectRatio() const noexcept {
if (this->height == 0) return 1.0F;
[[nodiscard]] constexpr auto getAspectRatio() const noexcept {
if (this->m_height == 0) return 1.0F;
return float(this->width) / float(this->height);
return float(this->m_width) / float(this->m_height);
}
private:
ImTextureID m_textureId = nullptr;
int m_width = 0, m_height = 0;
};
int UpdateStringSizeCallback(ImGuiInputTextCallbackData *data);
@@ -82,10 +95,6 @@ namespace ImGui {
return static_cast<ImU32>(ImGui::GetTime() * 100) % 100 <= static_cast<ImU32>(ImGui::GetIO().DeltaTime * 100);
}
Texture LoadImageFromPath(const char *path);
Texture LoadImageFromMemory(const ImU8 *buffer, int size);
void UnloadImage(Texture &texture);
void OpenPopupInWindow(const char *window_name, const char *popup_name);
struct ImHexCustomData {

View File

@@ -17,6 +17,74 @@
namespace ImGui {
Texture::Texture(const ImU8 *buffer, int size) {
unsigned char *imageData = stbi_load_from_memory(buffer, size, &this->m_width, &this->m_height, nullptr, 4);
if (imageData == nullptr)
return;
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
#if defined(GL_UNPACK_ROW_LENGTH)
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
#endif
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->m_width, this->m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
stbi_image_free(imageData);
this->m_textureId = reinterpret_cast<ImTextureID>(static_cast<intptr_t>(texture));
}
Texture::Texture(const char *path) {
unsigned char *imageData = stbi_load(path, &this->m_width, &this->m_height, nullptr, 4);
if (imageData == nullptr)
return;
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
#if defined(GL_UNPACK_ROW_LENGTH)
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
#endif
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->m_width, this->m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
stbi_image_free(imageData);
this->m_textureId = reinterpret_cast<ImTextureID>(static_cast<intptr_t>(texture));
}
Texture::Texture(Texture&& other) noexcept {
this->m_textureId = other.m_textureId;
this->m_width = other.m_width;
this->m_height = other.m_height;
other.m_textureId = nullptr;
}
void Texture::operator=(Texture&& other) noexcept {
this->m_textureId = other.m_textureId;
this->m_width = other.m_width;
this->m_height = other.m_height;
other.m_textureId = nullptr;
}
Texture::~Texture() {
if (this->m_textureId == nullptr)
return;
auto glTextureId = static_cast<GLuint>(reinterpret_cast<intptr_t>(this->m_textureId));
glDeleteTextures(1, &glTextureId);
}
int UpdateStringSizeCallback(ImGuiInputTextCallbackData *data) {
if (data->EventFlag == ImGuiInputTextFlags_CallbackResize) {
auto &string = *static_cast<std::string *>(data->UserData);
@@ -298,66 +366,6 @@ namespace ImGui {
colors[ImGuiCustomCol_Highlight] = ImColor(77, 198, 155);
}
Texture LoadImageFromPath(const char *path) {
int imageWidth = 0;
int imageHeight = 0;
unsigned char *imageData = stbi_load(path, &imageWidth, &imageHeight, nullptr, 4);
if (imageData == nullptr)
return { nullptr, -1, -1 };
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
#if defined(GL_UNPACK_ROW_LENGTH)
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
#endif
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imageWidth, imageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
stbi_image_free(imageData);
return { reinterpret_cast<ImTextureID>(static_cast<intptr_t>(texture)), imageWidth, imageHeight };
}
Texture LoadImageFromMemory(const ImU8 *buffer, int size) {
int imageWidth = 0;
int imageHeight = 0;
unsigned char *imageData = stbi_load_from_memory(buffer, size, &imageWidth, &imageHeight, nullptr, 4);
if (imageData == nullptr)
return { nullptr, -1, -1 };
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
#if defined(GL_UNPACK_ROW_LENGTH)
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
#endif
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imageWidth, imageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
stbi_image_free(imageData);
return { reinterpret_cast<ImTextureID>(static_cast<intptr_t>(texture)), imageWidth, imageHeight };
}
void UnloadImage(Texture &texture) {
if (texture.textureId == nullptr)
return;
auto glTextureId = static_cast<GLuint>(reinterpret_cast<intptr_t>(texture.textureId));
glDeleteTextures(1, &glTextureId);
texture = { nullptr, 0, 0 };
}
void OpenPopupInWindow(const char *window_name, const char *popup_name) {
if (ImGui::Begin(window_name)) {
ImGui::OpenPopup(popup_name);