Add OpenGL support in freetype fonts
All checks were successful
Run tests / Run tests (push) Successful in 6m55s

This commit is contained in:
Nikita Lisitsa 2026-07-25 03:13:09 +03:00
parent 68650da6f5
commit 04cde80596
2 changed files with 53 additions and 9 deletions

View file

@ -5,7 +5,7 @@
#include <psemek/util/span.hpp>
#if defined(PSEMEK_GRAPHICS_API_OPENGL)
#error "Fonts v2 don't support OpenGL yet"
#include <psemek/gfx/texture.hpp>
#elif defined(PSEMEK_GRAPHICS_API_WEBGPU)
#include <psemek/wgpu/device.hpp>
#include <psemek/wgpu/texture_view.hpp>
@ -29,7 +29,7 @@ namespace psemek::fonts
};
#if defined(PSEMEK_GRAPHICS_API_OPENGL)
// TODO
using texture_type = gfx::texture_2d;
#elif defined(PSEMEK_GRAPHICS_API_WEBGPU)
using texture_type = wgpu::texture_view;
#endif
@ -90,9 +90,17 @@ namespace psemek::fonts
virtual ~font_builder() {}
};
std::unique_ptr<font_builder> load_freetype_font(wgpu::device device, std::filesystem::path const & path);
struct font_options
{
#if defined(PSEMEK_GRAPHICS_API_OPENGL)
bool nearest_filter = false;
#elif defined(PSEMEK_GRAPHICS_API_WEBGPU)
wgpu::device device;
#endif
};
// Font paths are specified in order
std::unique_ptr<font_builder> load_combined_freetype_font(wgpu::device device, std::vector<std::filesystem::path> const & paths);
std::unique_ptr<font_builder> load_freetype_font(font_options const & options, std::filesystem::path const & path);
// Font paths are specified in order of priority
std::unique_ptr<font_builder> load_combined_freetype_font(font_options const & options, std::vector<std::filesystem::path> const & paths);
}

View file

@ -71,7 +71,11 @@ namespace psemek::fonts
struct face_shared
{
#if defined(PSEMEK_GRAPHICS_API_OPENGL)
bool nearest_filter;
#elif defined(PSEMEK_GRAPHICS_API_WEBGPU)
wgpu::device device;
#endif
struct face_data
{
@ -81,6 +85,15 @@ namespace psemek::fonts
std::vector<face_data> faces = {};
face_shared(font_options const & options)
{
#if defined(PSEMEK_GRAPHICS_API_OPENGL)
nearest_filter = options.nearest_filter;
#elif defined(PSEMEK_GRAPHICS_API_WEBGPU)
device = options.device;
#endif
}
~face_shared()
{
for (auto const & face : faces)
@ -151,8 +164,13 @@ namespace psemek::fonts
int current_row_height = 0;
int current_row_x = 0;
#if defined(PSEMEK_GRAPHICS_API_OPENGL)
std::unique_ptr<gfx::texture_2d> texture;
#elif defined(PSEMEK_GRAPHICS_API_WEBGPU)
wgpu::texture texture;
std::unique_ptr<wgpu::texture_view> texture_view;
#endif
bool needs_update = true;
};
@ -274,6 +292,15 @@ namespace psemek::fonts
pages_.emplace_back();
pages_.back().pixmap.resize({page_size, page_size}, 0);
#if defined(PSEMEK_GRAPHICS_API_OPENGL)
pages_.back().texture = std::make_unique<gfx::texture_2d>();
pages_.back().texture->load<std::uint8_t>({page_size, page_size});
if (state_->nearest_filter)
pages_.back().texture->nearest_filter();
else
pages_.back().texture->linear_filter();
pages_.back().texture->clamp();
#elif defined(PSEMEK_GRAPHICS_API_WEBGPU)
pages_.back().texture = state_->device.create_texture({
.usage = wgpu::texture::usage::copy_dst | wgpu::texture::usage::texture_binding,
.dimension = wgpu::texture::dimension::_2d,
@ -286,6 +313,7 @@ namespace psemek::fonts
.dimension = wgpu::texture_view::dimension::_2d,
.usage = wgpu::texture::usage::texture_binding,
}));
#endif
}
data->page = pages_.size() - 1;
@ -312,7 +340,11 @@ namespace psemek::fonts
}
auto & result = shaped_text_.emplace_back();
#if defined(PSEMEK_GRAPHICS_API_OPENGL)
result.texture = pages_[data->page].texture.get();
#elif defined(PSEMEK_GRAPHICS_API_WEBGPU)
result.texture = pages_[data->page].texture_view.get();
#endif
result.position[0].min = pen[0] + data->offset[0];
result.position[0].max = result.position[0].min + data->part[0].length();
result.position[1].min = pen[1] + data->offset[1];
@ -332,7 +364,11 @@ namespace psemek::fonts
if (!page.needs_update) continue;
page.needs_update = false;
#if defined(PSEMEK_GRAPHICS_API_OPENGL)
page.texture->load(page.pixmap);
#elif defined(PSEMEK_GRAPHICS_API_WEBGPU)
state_->device.get_queue().write_texture({.texture = page.texture}, {(char *)page.pixmap.data(), page.pixmap.size()}, {.bytes_per_row = page_size, .rows_per_image = page_size}, {page_size, page_size, 1});
#endif
}
}
@ -365,14 +401,14 @@ namespace psemek::fonts
}
std::unique_ptr<font_builder> load_freetype_font(wgpu::device device, std::filesystem::path const & path)
std::unique_ptr<font_builder> load_freetype_font(font_options const & options, std::filesystem::path const & path)
{
return load_combined_freetype_font(device, {path});
return load_combined_freetype_font(options, {path});
}
std::unique_ptr<font_builder> load_combined_freetype_font(wgpu::device device, std::vector<std::filesystem::path> const & paths)
std::unique_ptr<font_builder> load_combined_freetype_font(font_options const & options, std::vector<std::filesystem::path> const & paths)
{
auto result = std::make_shared<face_shared>(device);
auto result = std::make_shared<face_shared>(options);
for (auto const & path : paths)
{