Move font render mapping to renderer gl
This commit is contained in:
@@ -161,7 +161,10 @@ Known local toolchain state:
|
|||||||
the legacy convert command and resize path. App clear color-buffer masks,
|
the legacy convert command and resize path. App clear color-buffer masks,
|
||||||
default framebuffer binding, scissor state, and sampler filter/wrap tokens
|
default framebuffer binding, scissor state, and sampler filter/wrap tokens
|
||||||
also consume the backend mapping. OpenGL extension enumeration query 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
|
- `windows-msvc-vcpkg-headless` validates manifest install/configure/build/test
|
||||||
for the current headless component matrix; see DEBT-0007 for remaining app
|
for the current headless component matrix; see DEBT-0007 for remaining app
|
||||||
and platform triplet migration.
|
and platform triplet migration.
|
||||||
|
|||||||
@@ -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
|
backend-owned mapping. App clear color-buffer masks, default framebuffer
|
||||||
binding, scissor state, and sampler filter/wrap tokens now share that backend
|
binding, scissor state, and sampler filter/wrap tokens now share that backend
|
||||||
mapping too. OpenGL extension enumeration query tokens used before runtime
|
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.
|
behind the renderer interfaces.
|
||||||
|
|
||||||
Implementation tasks:
|
Implementation tasks:
|
||||||
|
|||||||
95
src/font.cpp
95
src/font.cpp
@@ -5,6 +5,61 @@
|
|||||||
#include "asset.h"
|
#include "asset.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "app.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;
|
std::map<std::string, Font> FontManager::m_fonts;
|
||||||
Sampler FontManager::m_sampler;
|
Sampler FontManager::m_sampler;
|
||||||
@@ -52,7 +107,7 @@ bool Font::load(const std::string& ttf, int font_size, float font_scale)
|
|||||||
// offset = 0;
|
// offset = 0;
|
||||||
stbtt_BakeFontBitmap(file.m_data, 0, (float)font_size*scale, bitmap.get(), w, h, start_char, num_chars, chars.data());
|
stbtt_BakeFontBitmap(file.m_data, 0, (float)font_size*scale, bitmap.get(), w, h, start_char, num_chars, chars.data());
|
||||||
calc_bounds();
|
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();
|
file.close();
|
||||||
size = font_size;
|
size = font_size;
|
||||||
return true;
|
return true;
|
||||||
@@ -161,10 +216,10 @@ bool TextMesh::create()
|
|||||||
glBindVertexArray(font_array);
|
glBindVertexArray(font_array);
|
||||||
glEnableVertexAttribArray(0);
|
glEnableVertexAttribArray(0);
|
||||||
glEnableVertexAttribArray(1);
|
glEnableVertexAttribArray(1);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, font_buffers[1]);
|
glBindBuffer(element_array_buffer_target(), font_buffers[1]);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, font_buffers[0]);
|
glBindBuffer(array_buffer_target(), font_buffers[0]);
|
||||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec4), (GLvoid*)0);
|
glVertexAttribPointer(0, 2, vertex_attribute_float_component_type(), vertex_attribute_not_normalized(), sizeof(glm::vec4), (GLvoid*)0);
|
||||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec4), (GLvoid*)(sizeof(float) * 2));
|
glVertexAttribPointer(1, 2, vertex_attribute_float_component_type(), vertex_attribute_not_normalized(), sizeof(glm::vec4), (GLvoid*)(sizeof(float) * 2));
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
#endif // USE_VBO
|
#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();
|
font_array_count = (int)idx.size();
|
||||||
App::I->render_task([&]
|
App::I->render_task([&]
|
||||||
{
|
{
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, font_buffers[1]);
|
glBindBuffer(element_array_buffer_target(), font_buffers[1]);
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, idx.size() * sizeof(GLushort), idx.data(), GL_STATIC_DRAW);
|
glBufferData(element_array_buffer_target(), idx.size() * sizeof(GLushort), idx.data(), static_draw_buffer_usage());
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, font_buffers[0]);
|
glBindBuffer(array_buffer_target(), font_buffers[0]);
|
||||||
glBufferData(GL_ARRAY_BUFFER, v.size() * sizeof(glm::vec4), v.data(), GL_STATIC_DRAW);
|
glBufferData(array_buffer_target(), v.size() * sizeof(glm::vec4), v.data(), static_draw_buffer_usage());
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(array_buffer_target(), 0);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
glBindBuffer(element_array_buffer_target(), 0);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -269,26 +324,26 @@ void TextMesh::draw()
|
|||||||
auto& f = FontManager::get(font, size, weight, italic);
|
auto& f = FontManager::get(font, size, weight, italic);
|
||||||
if (f.font_tex.ready())
|
if (f.font_tex.ready())
|
||||||
{
|
{
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(texture_unit(0U));
|
||||||
f.font_tex.bind();
|
f.font_tex.bind();
|
||||||
FontManager::m_sampler.bind(0);
|
FontManager::m_sampler.bind(0);
|
||||||
|
|
||||||
#if USE_VBO
|
#if USE_VBO
|
||||||
glBindVertexArray(font_array);
|
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);
|
glBindVertexArray(0);
|
||||||
#else
|
#else
|
||||||
glEnableVertexAttribArray(0);
|
glEnableVertexAttribArray(0);
|
||||||
glEnableVertexAttribArray(1);
|
glEnableVertexAttribArray(1);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, font_buffers[1]);
|
glBindBuffer(element_array_buffer_target(), font_buffers[1]);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, font_buffers[0]);
|
glBindBuffer(array_buffer_target(), font_buffers[0]);
|
||||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec4), (GLvoid*)0);
|
glVertexAttribPointer(0, 2, vertex_attribute_float_component_type(), vertex_attribute_not_normalized(), sizeof(glm::vec4), (GLvoid*)0);
|
||||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec4), (GLvoid*)(sizeof(float) * 2));
|
glVertexAttribPointer(1, 2, vertex_attribute_float_component_type(), vertex_attribute_not_normalized(), sizeof(glm::vec4), (GLvoid*)(sizeof(float) * 2));
|
||||||
glDrawElements(GL_TRIANGLES, font_array_count, GL_UNSIGNED_SHORT, 0);
|
glDrawElements(text_mesh_primitive_mode(), font_array_count, text_mesh_index_type(), 0);
|
||||||
glDisableVertexAttribArray(0);
|
glDisableVertexAttribArray(0);
|
||||||
glDisableVertexAttribArray(1);
|
glDisableVertexAttribArray(1);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(array_buffer_target(), 0);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
glBindBuffer(element_array_buffer_target(), 0);
|
||||||
#endif // USE_VBO
|
#endif // USE_VBO
|
||||||
|
|
||||||
f.font_tex.unbind();
|
f.font_tex.unbind();
|
||||||
|
|||||||
@@ -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_texture_border_color = 0x1004U;
|
||||||
constexpr std::uint32_t gl_repeat = 0x2901U;
|
constexpr std::uint32_t gl_repeat = 0x2901U;
|
||||||
constexpr std::uint32_t gl_clamp_to_edge = 0x812FU;
|
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_pack_buffer = 0x88EBU;
|
||||||
constexpr std::uint32_t gl_pixel_unpack_buffer = 0x88ECU;
|
constexpr std::uint32_t gl_pixel_unpack_buffer = 0x88ECU;
|
||||||
constexpr std::uint32_t gl_stream_read = 0x88E1U;
|
constexpr std::uint32_t gl_stream_read = 0x88E1U;
|
||||||
@@ -539,6 +540,11 @@ std::uint32_t repeat_texture_wrap() noexcept
|
|||||||
return gl_repeat;
|
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
|
std::uint32_t texture_cube_map_target() noexcept
|
||||||
{
|
{
|
||||||
return gl_texture_cube_map;
|
return gl_texture_cube_map;
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ struct OpenGlReadbackFormat {
|
|||||||
[[nodiscard]] std::uint32_t linear_texture_filter() noexcept;
|
[[nodiscard]] std::uint32_t linear_texture_filter() noexcept;
|
||||||
[[nodiscard]] std::uint32_t nearest_texture_filter() noexcept;
|
[[nodiscard]] std::uint32_t nearest_texture_filter() noexcept;
|
||||||
[[nodiscard]] std::uint32_t repeat_texture_wrap() 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 texture_cube_map_target() noexcept;
|
||||||
[[nodiscard]] std::uint32_t cube_map_allocation_face_texture_target(std::uint32_t face_index) 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;
|
[[nodiscard]] std::span<const std::uint32_t> panopainter_cube_face_texture_targets() noexcept;
|
||||||
|
|||||||
@@ -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::linear_texture_filter() == 0x2601U);
|
||||||
PP_EXPECT(h, pp::renderer::gl::nearest_texture_filter() == 0x2600U);
|
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::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)
|
void rejects_invalid_shader_attribute_binding_catalogs(pp::tests::Harness& h)
|
||||||
|
|||||||
Reference in New Issue
Block a user