...
This commit is contained in:
150
source/opengl/data_managers/texture_manager.cpp
Normal file
150
source/opengl/data_managers/texture_manager.cpp
Normal file
@@ -0,0 +1,150 @@
|
||||
#include "opengl/data_managers/texture_manager.hpp"
|
||||
|
||||
#include <ranges>
|
||||
#include "util/logger.hpp"
|
||||
#include "opengl/error.hpp"
|
||||
|
||||
|
||||
void zgl::texture_manager::process(
|
||||
dynamic_texture_store& store
|
||||
) {
|
||||
m_texture_buffer.clear();
|
||||
|
||||
for (const auto& [ id, texture ] : store)
|
||||
{
|
||||
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 components::texture::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());
|
||||
return;
|
||||
}
|
||||
|
||||
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()
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user