Files
Z3D/source/opengl/data_managers/texture_manager.cpp
2025-03-25 15:57:32 +01:00

150 lines
3.5 KiB
C++

#include "opengl/data_managers/texture_manager.hpp"
#include <ranges>
#include "util/logger.hpp"
#include "opengl/error.hpp"
void zgl::texture_manager::process(
const assets::data_stores& stores
) {
m_texture_buffer.clear();
for (const auto& [ id, texture ] : stores.textures)
{
if (not m_resource_manager.has_resource(id))
{
m_texture_buffer.emplace_back(id, texture);
}
}
m_texture_id_buffer.resize(m_texture_buffer.size());
glGenTextures(m_texture_id_buffer.size(), m_texture_id_buffer.data());
if (const auto e = get_error())
{
ztu::logger::error("Error while creating % textures: %.", m_texture_id_buffer.size(), e.message());
return;
}
for (auto [ entry, texture_id ] : std::ranges::views::zip(m_texture_buffer, m_texture_id_buffer))
{
auto [ store_id, texture ] = entry;
GLenum format;
switch (texture.components()) {
using enum assets::texture_components::flags;
case luminance:
format = GL_LUMINANCE;
break;
case luminance | alpha:
format = GL_LUMINANCE_ALPHA;
break;
case red | green | blue:
format = GL_RGB;
break;
case red | green | blue | alpha:
format = GL_RGBA;
break;
default:
// TODO create a print statement for these enum flaggy thingies
ztu::logger::error("Unsupported texture component configuration: %.", texture.components());
continue;
}
glBindTexture(GL_TEXTURE_2D, texture_id);
if (const auto e = get_error())
{
ztu::logger::error("Error while binding texture %: %.", texture_id, e.message());
continue;
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if (const auto e = get_error())
{
ztu::logger::warn("Error while setting texture parameters: %.", e.message());
}
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RGBA8,
texture.width(),
texture.height(),
0,
format,
GL_UNSIGNED_BYTE,
texture.data()
);
if (const auto e = get_error())
{
ztu::logger::error("Error while setting texture data: %.", e.message());
continue;
}
glGenerateMipmap(GL_TEXTURE_2D);
if (const auto e = get_error())
{
ztu::logger::warn("Error while generating texture mipmaps: %.", e.message());
}
const auto meta = metadata_type{
.components = texture.components()
};
m_resource_manager.add_resource(store_id, texture_id, meta);
texture_id = {};
}
glBindTexture(GL_TEXTURE_2D, 0);
const auto valid_texture_ids = std::ranges::remove(
m_texture_id_buffer,
0
);
const auto invalid_texture_count = m_texture_id_buffer.size() - valid_texture_ids.size();
glDeleteTextures(
invalid_texture_count,
m_texture_id_buffer.data()
);
if (const auto e = get_error())
{
ztu::logger::error("Error while deleting % textures: %.", invalid_texture_count, e.message());
}
}
std::optional<zgl::texture_manager::handle_type> zgl::texture_manager::get_handle(
const store_id_type id
) {
return m_resource_manager
.get_resource(id)
.transform(
[](auto& resource)
{
return *reinterpret_cast<handle_type*>(resource);
}
);
}
void zgl::texture_manager::collect_garbage(const bool force)
{
m_resource_manager.collect_garbage();
if (force or m_resource_manager.count_garbage() >= min_garbage_collection_count)
{
m_texture_id_buffer.clear();
m_resource_manager.extract_garbage(m_texture_id_buffer);
glDeleteTextures(
m_texture_id_buffer.size(),
m_texture_id_buffer.data()
);
}
}