From d0b0dc3865f558848960afc0a5fc0cba9e8facce Mon Sep 17 00:00:00 2001 From: omigamedev Date: Tue, 2 Jun 2026 07:36:09 +0200 Subject: [PATCH] Move font render mapping to renderer gl --- docs/modernization/build-inventory.md | 5 +- docs/modernization/roadmap.md | 6 +- src/font.cpp | 95 +++++++++++++++++++----- src/renderer_gl/opengl_capabilities.cpp | 6 ++ src/renderer_gl/opengl_capabilities.h | 1 + tests/renderer_gl/capabilities_tests.cpp | 2 + 6 files changed, 93 insertions(+), 22 deletions(-) diff --git a/docs/modernization/build-inventory.md b/docs/modernization/build-inventory.md index 7ace16a..d3aabf8 100644 --- a/docs/modernization/build-inventory.md +++ b/docs/modernization/build-inventory.md @@ -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. diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index 20e3946..4f762b8 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -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: diff --git a/src/font.cpp b/src/font.cpp index 1e7ba6d..a64bde2 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -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(pp::renderer::gl::texture_format_for_channel_count(1U).internal_format); +} + +[[nodiscard]] GLint font_atlas_pixel_format() noexcept +{ + return static_cast(pp::renderer::gl::texture_format_for_channel_count(1U).pixel_format); +} + +[[nodiscard]] GLenum element_array_buffer_target() noexcept +{ + return static_cast(pp::renderer::gl::element_array_buffer_target()); +} + +[[nodiscard]] GLenum array_buffer_target() noexcept +{ + return static_cast(pp::renderer::gl::array_buffer_target()); +} + +[[nodiscard]] GLenum static_draw_buffer_usage() noexcept +{ + return static_cast(pp::renderer::gl::static_draw_buffer_usage()); +} + +[[nodiscard]] GLenum vertex_attribute_float_component_type() noexcept +{ + return static_cast(pp::renderer::gl::vertex_attribute_float_component_type()); +} + +[[nodiscard]] GLboolean vertex_attribute_not_normalized() noexcept +{ + return static_cast(pp::renderer::gl::vertex_attribute_not_normalized()); +} + +[[nodiscard]] GLenum text_mesh_primitive_mode() noexcept +{ + return static_cast(pp::renderer::gl::primitive_mode_for_fill_count(3U)); +} + +[[nodiscard]] GLenum text_mesh_index_type() noexcept +{ + return static_cast(pp::renderer::gl::index_type_for_index_size(sizeof(GLushort))); +} + +[[nodiscard]] GLenum texture_unit(std::uint32_t unit_index) noexcept +{ + return static_cast(pp::renderer::gl::active_texture_unit(unit_index)); +} + +} std::map 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(); diff --git a/src/renderer_gl/opengl_capabilities.cpp b/src/renderer_gl/opengl_capabilities.cpp index 2f24e52..93fcd6a 100644 --- a/src/renderer_gl/opengl_capabilities.cpp +++ b/src/renderer_gl/opengl_capabilities.cpp @@ -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; diff --git a/src/renderer_gl/opengl_capabilities.h b/src/renderer_gl/opengl_capabilities.h index 24efe26..3e304bb 100644 --- a/src/renderer_gl/opengl_capabilities.h +++ b/src/renderer_gl/opengl_capabilities.h @@ -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 panopainter_cube_face_texture_targets() noexcept; diff --git a/tests/renderer_gl/capabilities_tests.cpp b/tests/renderer_gl/capabilities_tests.cpp index 680d449..dfd24ab 100644 --- a/tests/renderer_gl/capabilities_tests.cpp +++ b/tests/renderer_gl/capabilities_tests.cpp @@ -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)