149 lines
3.5 KiB
C++
149 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 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::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()
|
|
);
|
|
}
|
|
} |