Move font render mapping to renderer gl

This commit is contained in:
2026-06-02 07:36:09 +02:00
parent 6fc8b9e5d2
commit d0b0dc3865
6 changed files with 93 additions and 22 deletions

View File

@@ -161,7 +161,10 @@ Known local toolchain state:
the legacy convert command and resize path. App clear color-buffer masks,
default framebuffer binding, scissor state, and sampler filter/wrap tokens
also consume the backend mapping. OpenGL extension enumeration query tokens
used before runtime capability detection are cataloged here.
used before runtime capability detection are cataloged here. Legacy font
atlas texture formats, text mesh buffer targets, attribute component and
normalization tokens, draw primitive/index type, upload usage, and active
texture unit selection also consume the backend mapping.
- `windows-msvc-vcpkg-headless` validates manifest install/configure/build/test
for the current headless component matrix; see DEBT-0007 for remaining app
and platform triplet migration.

View File

@@ -426,7 +426,11 @@ and UI render-target RGBA8 format tokens are now also cataloged and tested in
backend-owned mapping. App clear color-buffer masks, default framebuffer
binding, scissor state, and sampler filter/wrap tokens now share that backend
mapping too. OpenGL extension enumeration query tokens used before runtime
capability detection also live in `pp_renderer_gl`. The existing renderer classes are not yet fully
capability detection also live in `pp_renderer_gl`. Legacy font atlas texture
formats, text mesh buffer targets, attribute component/normalization, draw
primitive/index type, upload usage, and active texture unit selection also
delegate to `pp_renderer_gl`; `Font` no longer spells GL enum names directly.
The existing renderer classes are not yet fully
behind the renderer interfaces.
Implementation tasks:

View File

@@ -5,6 +5,61 @@
#include "asset.h"
#include "util.h"
#include "app.h"
#include "renderer_gl/opengl_capabilities.h"
namespace {
[[nodiscard]] GLint font_atlas_internal_format() noexcept
{
return static_cast<GLint>(pp::renderer::gl::texture_format_for_channel_count(1U).internal_format);
}
[[nodiscard]] GLint font_atlas_pixel_format() noexcept
{
return static_cast<GLint>(pp::renderer::gl::texture_format_for_channel_count(1U).pixel_format);
}
[[nodiscard]] GLenum element_array_buffer_target() noexcept
{
return static_cast<GLenum>(pp::renderer::gl::element_array_buffer_target());
}
[[nodiscard]] GLenum array_buffer_target() noexcept
{
return static_cast<GLenum>(pp::renderer::gl::array_buffer_target());
}
[[nodiscard]] GLenum static_draw_buffer_usage() noexcept
{
return static_cast<GLenum>(pp::renderer::gl::static_draw_buffer_usage());
}
[[nodiscard]] GLenum vertex_attribute_float_component_type() noexcept
{
return static_cast<GLenum>(pp::renderer::gl::vertex_attribute_float_component_type());
}
[[nodiscard]] GLboolean vertex_attribute_not_normalized() noexcept
{
return static_cast<GLboolean>(pp::renderer::gl::vertex_attribute_not_normalized());
}
[[nodiscard]] GLenum text_mesh_primitive_mode() noexcept
{
return static_cast<GLenum>(pp::renderer::gl::primitive_mode_for_fill_count(3U));
}
[[nodiscard]] GLenum text_mesh_index_type() noexcept
{
return static_cast<GLenum>(pp::renderer::gl::index_type_for_index_size(sizeof(GLushort)));
}
[[nodiscard]] GLenum texture_unit(std::uint32_t unit_index) noexcept
{
return static_cast<GLenum>(pp::renderer::gl::active_texture_unit(unit_index));
}
}
std::map<std::string, Font> FontManager::m_fonts;
Sampler FontManager::m_sampler;
@@ -52,7 +107,7 @@ bool Font::load(const std::string& ttf, int font_size, float font_scale)
// offset = 0;
stbtt_BakeFontBitmap(file.m_data, 0, (float)font_size*scale, bitmap.get(), w, h, start_char, num_chars, chars.data());
calc_bounds();
font_tex.create(w, h, GL_R8, GL_RED, bitmap.get());
font_tex.create(w, h, font_atlas_internal_format(), font_atlas_pixel_format(), bitmap.get());
file.close();
size = font_size;
return true;
@@ -161,10 +216,10 @@ bool TextMesh::create()
glBindVertexArray(font_array);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, font_buffers[1]);
glBindBuffer(GL_ARRAY_BUFFER, font_buffers[0]);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec4), (GLvoid*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec4), (GLvoid*)(sizeof(float) * 2));
glBindBuffer(element_array_buffer_target(), font_buffers[1]);
glBindBuffer(array_buffer_target(), font_buffers[0]);
glVertexAttribPointer(0, 2, vertex_attribute_float_component_type(), vertex_attribute_not_normalized(), sizeof(glm::vec4), (GLvoid*)0);
glVertexAttribPointer(1, 2, vertex_attribute_float_component_type(), vertex_attribute_not_normalized(), sizeof(glm::vec4), (GLvoid*)(sizeof(float) * 2));
glBindVertexArray(0);
#endif // USE_VBO
});
@@ -254,12 +309,12 @@ void TextMesh::update(const std::string& text, const std::string& font, int size
font_array_count = (int)idx.size();
App::I->render_task([&]
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, font_buffers[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, idx.size() * sizeof(GLushort), idx.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, font_buffers[0]);
glBufferData(GL_ARRAY_BUFFER, v.size() * sizeof(glm::vec4), v.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(element_array_buffer_target(), font_buffers[1]);
glBufferData(element_array_buffer_target(), idx.size() * sizeof(GLushort), idx.data(), static_draw_buffer_usage());
glBindBuffer(array_buffer_target(), font_buffers[0]);
glBufferData(array_buffer_target(), v.size() * sizeof(glm::vec4), v.data(), static_draw_buffer_usage());
glBindBuffer(array_buffer_target(), 0);
glBindBuffer(element_array_buffer_target(), 0);
});
}
}
@@ -269,26 +324,26 @@ void TextMesh::draw()
auto& f = FontManager::get(font, size, weight, italic);
if (f.font_tex.ready())
{
glActiveTexture(GL_TEXTURE0);
glActiveTexture(texture_unit(0U));
f.font_tex.bind();
FontManager::m_sampler.bind(0);
#if USE_VBO
glBindVertexArray(font_array);
glDrawElements(GL_TRIANGLES, font_array_count, GL_UNSIGNED_SHORT, 0);
glDrawElements(text_mesh_primitive_mode(), font_array_count, text_mesh_index_type(), 0);
glBindVertexArray(0);
#else
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, font_buffers[1]);
glBindBuffer(GL_ARRAY_BUFFER, font_buffers[0]);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec4), (GLvoid*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec4), (GLvoid*)(sizeof(float) * 2));
glDrawElements(GL_TRIANGLES, font_array_count, GL_UNSIGNED_SHORT, 0);
glBindBuffer(element_array_buffer_target(), font_buffers[1]);
glBindBuffer(array_buffer_target(), font_buffers[0]);
glVertexAttribPointer(0, 2, vertex_attribute_float_component_type(), vertex_attribute_not_normalized(), sizeof(glm::vec4), (GLvoid*)0);
glVertexAttribPointer(1, 2, vertex_attribute_float_component_type(), vertex_attribute_not_normalized(), sizeof(glm::vec4), (GLvoid*)(sizeof(float) * 2));
glDrawElements(text_mesh_primitive_mode(), font_array_count, text_mesh_index_type(), 0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(array_buffer_target(), 0);
glBindBuffer(element_array_buffer_target(), 0);
#endif // USE_VBO
f.font_tex.unbind();

View File

@@ -91,6 +91,7 @@ constexpr std::uint32_t gl_texture_wrap_r = 0x8072U;
constexpr std::uint32_t gl_texture_border_color = 0x1004U;
constexpr std::uint32_t gl_repeat = 0x2901U;
constexpr std::uint32_t gl_clamp_to_edge = 0x812FU;
constexpr std::uint32_t gl_texture0 = 0x84C0U;
constexpr std::uint32_t gl_pixel_pack_buffer = 0x88EBU;
constexpr std::uint32_t gl_pixel_unpack_buffer = 0x88ECU;
constexpr std::uint32_t gl_stream_read = 0x88E1U;
@@ -539,6 +540,11 @@ std::uint32_t repeat_texture_wrap() noexcept
return gl_repeat;
}
std::uint32_t active_texture_unit(std::uint32_t unit_index) noexcept
{
return gl_texture0 + unit_index;
}
std::uint32_t texture_cube_map_target() noexcept
{
return gl_texture_cube_map;

View File

@@ -111,6 +111,7 @@ struct OpenGlReadbackFormat {
[[nodiscard]] std::uint32_t linear_texture_filter() noexcept;
[[nodiscard]] std::uint32_t nearest_texture_filter() noexcept;
[[nodiscard]] std::uint32_t repeat_texture_wrap() noexcept;
[[nodiscard]] std::uint32_t active_texture_unit(std::uint32_t unit_index) noexcept;
[[nodiscard]] std::uint32_t texture_cube_map_target() noexcept;
[[nodiscard]] std::uint32_t cube_map_allocation_face_texture_target(std::uint32_t face_index) noexcept;
[[nodiscard]] std::span<const std::uint32_t> panopainter_cube_face_texture_targets() noexcept;

View File

@@ -336,6 +336,8 @@ void maps_app_initialization_parameters(pp::tests::Harness& h)
PP_EXPECT(h, pp::renderer::gl::linear_texture_filter() == 0x2601U);
PP_EXPECT(h, pp::renderer::gl::nearest_texture_filter() == 0x2600U);
PP_EXPECT(h, pp::renderer::gl::repeat_texture_wrap() == 0x2901U);
PP_EXPECT(h, pp::renderer::gl::active_texture_unit(0U) == 0x84C0U);
PP_EXPECT(h, pp::renderer::gl::active_texture_unit(4U) == 0x84C4U);
}
void rejects_invalid_shader_attribute_binding_catalogs(pp::tests::Harness& h)