#include "opengl/data_managers/texture_manager.hpp" #include #include "util/logger.hpp" #include "opengl/error.hpp" void zgl::texture_manager::process(const store_type& textures) { m_texture_buffer.clear(); for (const auto& [ id, texture ] : 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::get_handle( const store_id_type id ) { return m_resource_manager .get_resource(id) .transform( [](auto& resource) { return *reinterpret_cast(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() ); } }