Skip to content

Commit

Permalink
[fix] glyph atlas generation from OpenGL
Browse files Browse the repository at this point in the history
  • Loading branch information
MrsRina committed Mar 30, 2024
1 parent 91d2e92 commit ce26be4
Show file tree
Hide file tree
Showing 11 changed files with 102 additions and 60 deletions.
6 changes: 4 additions & 2 deletions include/ekg/draw/font_renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ namespace ekg::draw {
FT_UInt ft_uint_previous {};
FT_Vector_ ft_vector_previous_char {};

std::string font_path {};
std::string_view font_path {};
uint32_t font_size {18};
ekg::gpu::sampler_t sampler_texture {};

Expand All @@ -55,6 +55,8 @@ namespace ekg::draw {

bool flag_unloaded {};
bool flag_first_time {true};
bool font_face_changed {};
bool font_size_changed {};

ekg::gpu::allocator *p_allocator {};
ekg::draw::glyph_char_t allocated_char_data[256] {};
Expand Down Expand Up @@ -84,7 +86,7 @@ namespace ekg::draw {
/**
* Set a new font face, check FreeType docs.
*/
void set_font(const std::string &font_face_path);
void set_font(std::string_view font_face_path);

/**
* Set the font face height.
Expand Down
1 change: 1 addition & 0 deletions include/ekg/gpu/allocator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ namespace ekg::gpu {
bool factor_changed {};
bool simple_shape {};
bool out_of_scissor_rect {};
ekg::rect scissor_instance {};
public:
/*
* Init gpu allocator.
Expand Down
2 changes: 1 addition & 1 deletion include/ekg/os/ekg_opengl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ namespace ekg::os {

int32_t uniform_active_texture {};
int32_t uniform_active_tex_slot {};
int32_t uniform_color {};
int32_t uniform_content {};
int32_t uniform_rect {};
int32_t uniform_line_thickness {};
int32_t uniform_scissor {};
Expand Down
Binary file modified lib/windows/libekg.a
Binary file not shown.
21 changes: 6 additions & 15 deletions src/core/runtime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,9 @@ void ekg::runtime::update_size_changed() {
};

if (this->f_renderer_normal.font_size != font_size) {
this->f_renderer_small.font_size = ekg_min(font_size - 4, 4);
this->f_renderer_small.reload();

this->f_renderer_normal.font_size = ekg_min(font_size, 8);
this->f_renderer_normal.reload();

this->f_renderer_big.font_size = ekg_min(font_size + 6, 12);
this->f_renderer_big.reload();
this->f_renderer_small.set_size(ekg_min(font_size - 4, 4));
this->f_renderer_normal.set_size(ekg_min(font_size, 8));
this->f_renderer_big.set_size(ekg_min(font_size + 6, 12));
}

for (ekg::ui::abstract_widget *&p_widgets: this->loaded_widget_list) {
Expand All @@ -75,10 +70,6 @@ void ekg::runtime::update_size_changed() {
}

void ekg::runtime::init() {
if (FT_Init_FreeType(&ekg::draw::font_renderer::ft_library)) {
ekg::log() << "Error: Failed to init FreeType library";
}

this->gpu_allocator.init();
this->prepare_tasks();
this->prepare_ui_env();
Expand Down Expand Up @@ -542,13 +533,13 @@ void ekg::runtime::do_task_reload(ekg::ui::abstract_widget *p_widget) {
void ekg::runtime::prepare_ui_env() {
ekg::log() << "Preparing internal user interface environment";

this->f_renderer_small.font_size = 16;
this->f_renderer_small.set_size(16);
this->f_renderer_small.bind_allocator(&this->gpu_allocator);

this->f_renderer_normal.font_size = 0;
this->f_renderer_normal.set_size(0);
this->f_renderer_normal.bind_allocator(&this->gpu_allocator);

this->f_renderer_big.font_size = 24;
this->f_renderer_big.set_size(24);
this->f_renderer_big.bind_allocator(&this->gpu_allocator);
this->update_size_changed();

Expand Down
59 changes: 45 additions & 14 deletions src/draw/font_renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,34 +128,50 @@ float ekg::draw::font_renderer::get_text_height() {
return this->text_height;
}

void ekg::draw::font_renderer::set_font(const std::string &path) {
void ekg::draw::font_renderer::set_font(std::string_view path) {
if (this->font_path != path) {
this->font_path = path;
this->font_face_changed = true;
this->reload();
}
}

void ekg::draw::font_renderer::set_size(uint32_t size) {
if (this->font_size != size) {
this->font_size = size;
this->font_size_changed = true;
this->reload();
}
}

void ekg::draw::font_renderer::reload() {
if (!this->flag_first_time) {
FT_Done_Face(this->ft_face);
bool font_face_created {};

if (this->font_face_changed) {
if (!this->flag_first_time) {
FT_Done_Face(this->ft_face);
}

this->flag_unloaded = FT_New_Face(ekg::draw::font_renderer::ft_library, this->font_path.data(), 0, &this->ft_face);
this->font_face_changed = false;
font_face_created = true;
}

if (font_face_created && !this->font_size_changed) {
return;
}

this->flag_unloaded = FT_New_Face(ekg::draw::font_renderer::ft_library, this->font_path.c_str(), 0, &this->ft_face);
this->flag_first_time = false;

if (this->flag_unloaded) {
ekg::log() << "Error: Failed to create font face from '" << this->font_path << '\'';
return;
}

FT_Set_Pixel_Sizes(this->ft_face, 0, this->font_size);
if (this->font_size_changed) {
FT_Set_Pixel_Sizes(this->ft_face, 0, this->font_size);
this->font_size_changed = false;
}

/* Phase of getting bitmap texture bounds. */
this->full_width = 0;
Expand Down Expand Up @@ -260,15 +276,30 @@ void ekg::draw::font_renderer::blit(std::string_view text, float x, float y, con
coordinates.w = vertices.w / this->full_width;
coordinates.h = vertices.h / this->full_height;

this->p_allocator->push_back_geometry(vertices.x, vertices.y, coordinates.x, coordinates.y);
this->p_allocator->push_back_geometry(vertices.x, vertices.y + vertices.h, coordinates.x,
coordinates.y + coordinates.h);
this->p_allocator->push_back_geometry(vertices.x + vertices.w, vertices.y + vertices.h,
coordinates.x + coordinates.w, coordinates.y + coordinates.h);
this->p_allocator->push_back_geometry(vertices.x + vertices.w, vertices.y + vertices.h,
coordinates.x + coordinates.w, coordinates.y + coordinates.h);
this->p_allocator->push_back_geometry(vertices.x + vertices.w, vertices.y, coordinates.x + coordinates.w,
coordinates.y);
this->p_allocator->push_back_geometry(
vertices.x, vertices.y, coordinates.x, coordinates.y
);

this->p_allocator->push_back_geometry(
vertices.x, vertices.y + vertices.h, coordinates.x,
coordinates.y + coordinates.h
);

this->p_allocator->push_back_geometry(
vertices.x + vertices.w, vertices.y + vertices.h,
coordinates.x + coordinates.w, coordinates.y + coordinates.h
);

this->p_allocator->push_back_geometry(
vertices.x + vertices.w, vertices.y + vertices.h,
coordinates.x + coordinates.w, coordinates.y + coordinates.h
);

this->p_allocator->push_back_geometry(
vertices.x + vertices.w, vertices.y, coordinates.x + coordinates.w,
coordinates.y
);

this->p_allocator->push_back_geometry(vertices.x, vertices.y, coordinates.x, coordinates.y);

x += char_data.wsize;
Expand Down
10 changes: 7 additions & 3 deletions src/ekg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,14 @@ void ekg::init(

ekg::log() << "Initialising EKG";

if (FT_Init_FreeType(&ekg::draw::font_renderer::ft_library)) {
ekg::log() << "Error: Failed to init FreeType library";
}

ekg::core = p_ekg_runtime;
ekg::core->f_renderer_small.font_path = p_ekg_runtime_property->p_font_path;
ekg::core->f_renderer_normal.font_path = p_ekg_runtime_property->p_font_path;
ekg::core->f_renderer_big.font_path = p_ekg_runtime_property->p_font_path;
ekg::core->f_renderer_small.set_font(p_ekg_runtime_property->p_font_path);
ekg::core->f_renderer_normal.set_font(p_ekg_runtime_property->p_font_path);
ekg::core->f_renderer_big.set_font(p_ekg_runtime_property->p_font_path);
ekg::core->init();
}

Expand Down
40 changes: 23 additions & 17 deletions src/gpu/allocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,27 +29,22 @@ bool ekg::gpu::allocator::is_out_of_scissor {};
float ekg::gpu::allocator::concave {-2.0f};

void ekg::gpu::allocator::invoke() {
/*
* Invocation segment reset the CPU-batching counters.
*/
this->data_instance_index = 0;
this->begin_stride_count = 0;
this->end_stride_count = 0;
this->simple_shape_index = 0;
this->cached_geometry_index = 0;

/*
* The first 4 vertices are used by the simple shapes,
* soon it is necessary to add not even one simple shape indices
* but everything.
*/
/**
* inserting a simple triangle mesh,
* is necessary to make work the simple-shape
* rendering.
**/
this->push_back_geometry(0.0f, 0.0f, 0.0f, 0.0f);
this->push_back_geometry(0.0f, 1.0f, 0.0f, 1.0f);
this->push_back_geometry(1.0f, 0.0f, 1.0f, 0.0f);
this->push_back_geometry(1.0f, 1.0f, 1.0f, 1.0f);

/* unique shape data will break if not clear the first index. */

this->clear_current_data();
this->data_list.at(this->data_instance_index).begin_stride = this->end_stride_count;
this->begin_stride_count += this->end_stride_count;
Expand All @@ -64,7 +59,19 @@ void ekg::gpu::allocator::bind_texture(ekg::gpu::sampler_t *p_sampler) {
void ekg::gpu::allocator::dispatch() {
ekg::gpu::data_t &data {this->data_list.at(this->data_instance_index)};

/* if this data contains a simple rect shape scheme, save this index and reuse later */
/**
* Scissor must be synchned externally to update the scissor context
**/

data.buffer_content[8] = this->scissor_instance.x;
data.buffer_content[9] = this->scissor_instance.y;
data.buffer_content[10] = this->scissor_instance.w;
data.buffer_content[11] = this->scissor_instance.h;

/**
* the point of re-using a simple shape stride makes performance a little better,
* due the index rendering, with only one triangle for rectangles.
**/

this->simple_shape = (
static_cast<int32_t>(data.buffer_content[2]) != static_cast<int32_t>(ekg::gpu::allocator::concave) &&
Expand Down Expand Up @@ -137,12 +144,11 @@ void ekg::gpu::allocator::init() {
}

void ekg::gpu::allocator::clear_current_data() {
/* allocator handle automatically the size of data */

if (this->data_instance_index >= this->data_list.size()) {
this->data_list.emplace_back();
}

/* allocator handle automatically the size of data */
ekg::gpu::data_t &data {this->data_list.at(this->data_instance_index)};
data.line_thickness = 0;
data.sampler_index = -1;
Expand Down Expand Up @@ -210,10 +216,10 @@ void ekg::gpu::allocator::sync_scissor(ekg::rect &scissor, ekg::rect &rect_child
/**
* It is much better to waste memory than CPU runtime processing.
**/
data.buffer_content[8] = scissor.x;
data.buffer_content[9] = scissor.y;
data.buffer_content[10] = scissor.w;
data.buffer_content[11] = scissor.h;
this->scissor_instance.x = scissor.x;
this->scissor_instance.y = scissor.y;
this->scissor_instance.w = scissor.w;
this->scissor_instance.h = scissor.h;
}

void ekg::gpu::allocator::push_back_geometry(
Expand Down
16 changes: 9 additions & 7 deletions src/os/ekg_opengl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ void ekg::os::opengl::init() {

"void main() {\n"
" vec2 vertex = aPos;\n"
" bool modalShape = uRect.z < 0.0f;\n"
" bool modalShape = uRect.z > 0.0f;\n"

" if (modalShape) {"
" vertex *= uRect.zw;"
Expand Down Expand Up @@ -116,6 +116,7 @@ void ekg::os::opengl::init() {
" vFragColor = texture(uTextureSampler, vTexCoord);\n"
" vFragColor = vec4(vFragColor.xyz - ((1.0f - color.xyz) - 1.0f), vFragColor.w - (1.0f - color.w));\n"
" }\n"
" vFragColor = vec4(1.0f);\n"
"}"
};

Expand Down Expand Up @@ -162,7 +163,7 @@ void ekg::os::opengl::init() {
/* reduce glGetLocation calls when rendering the batch */
this->uniform_active_texture = glGetUniformLocation(this->pipeline_program, "uActiveTexture");
this->uniform_active_tex_slot = glGetUniformLocation(this->pipeline_program, "uTextureSampler");
this->uniform_color = glGetUniformLocation(this->pipeline_program, "uColor");
this->uniform_content = glGetUniformLocation(this->pipeline_program, "uContent");
this->uniform_rect = glGetUniformLocation(this->pipeline_program, "uRect");
this->uniform_line_thickness = glGetUniformLocation(this->pipeline_program, "uLineThickness");
this->uniform_scissor = glGetUniformLocation(this->pipeline_program, "uScissor");
Expand Down Expand Up @@ -192,6 +193,7 @@ void ekg::os::opengl::update_viewport(int32_t w, int32_t h) {

glUseProgram(this->pipeline_program);
glUniformMatrix4fv(this->uniform_projection, GL_FALSE, 1, ekg::gpu::api::projection);
glUniform1i(this->uniform_viewport_height, ekg::gpu::api::viewport[3]);
glUseProgram(0);
}

Expand Down Expand Up @@ -259,7 +261,7 @@ void ekg::os::opengl::re_alloc_geometry_resources(
glBindBuffer(GL_ARRAY_BUFFER, this->geometry_buffer);
glBufferData(
GL_ARRAY_BUFFER,
sizeof(p_data),
sizeof(float)*size,
p_data,
GL_STATIC_DRAW
);
Expand Down Expand Up @@ -359,7 +361,7 @@ uint64_t ekg::os::opengl::generate_font_atlas(
int32_t atlas_height,
ekg::draw::glyph_char_t *p_glyph_char_data
) {
int32_t internal_format {GL_RGBA};
int32_t internal_format {GL_RED};
#if defined(__ANDROID__)
/*
* Android does not support GL_RED, perharps because of the GL ES version.
Expand Down Expand Up @@ -482,7 +484,7 @@ void ekg::os::opengl::draw(
int32_t previous_sampler_bound {};
bool sampler_going_on {};

for (uint64_t it {}; it < loaded_gpu_data_size; it++) {
for (uint64_t it {}; it < loaded_gpu_data_size-1; it++) {
ekg::gpu::data_t &data {p_gpu_data[it]};
sampler_going_on = data.sampler_index > -1;

Expand Down Expand Up @@ -515,11 +517,11 @@ void ekg::os::opengl::draw(

glUniform1i(this->uniform_line_thickness, data.line_thickness);
glUniform4fv(this->uniform_rect, GL_TRUE, data.buffer_content);
glUniform1fv(this->uniform_color, 8, &data.buffer_content[4]);
glUniform1fv(this->uniform_content, 8, &data.buffer_content[4]);

switch (data.begin_stride) {
case 0: {
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, nullptr);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, (void*) 0);
break;
}

Expand Down
Binary file modified test/build/windows/ekg-gui-showcase-test.exe
Binary file not shown.
7 changes: 6 additions & 1 deletion test/src/ekg_gui_showcase_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
int32_t showcase_useless_window() {
SDL_Init(SDL_INIT_VIDEO);

SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 4);
SDL_GL_SetSwapInterval(1);

SDL_Window *p_sdl_win {
SDL_CreateWindow(
"Pompom",
Expand Down Expand Up @@ -53,7 +58,7 @@ int32_t showcase_useless_window() {
}

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.6f, 0.0f, 0.6f, 0.993f);
glClearColor(0.6f, 0.6f, 0.6f, 0.993f);

ekg::ui::dt = 0.016f;
ekg::update();
Expand Down

0 comments on commit ce26be4

Please sign in to comment.