diff options
| -rw-r--r-- | Makefile | 1 | ||||
| -rw-r--r-- | src/atlas.cc | 92 | ||||
| -rw-r--r-- | src/atlas.h | 23 | ||||
| -rw-r--r-- | src/text.cc | 52 | ||||
| -rw-r--r-- | src/text.h | 24 |
5 files changed, 171 insertions, 21 deletions
@@ -95,6 +95,7 @@ SOURCES = \ $(SRC_DIR)/graphics.cc \ $(SRC_DIR)/gfx.c \ $(SRC_DIR)/text.cc \ + $(SRC_DIR)/atlas.cc \ $(GLAD_DIR)/glad.c \ $(ASSETS_DIR)/text_shader.c \ $(HASHMAP_SOURCE) diff --git a/src/atlas.cc b/src/atlas.cc new file mode 100644 index 0000000..4b756eb --- /dev/null +++ b/src/atlas.cc @@ -0,0 +1,92 @@ +#include "atlas.h" + +#include "mimalloc.h" +#include "utils.h" + +static void wayc_atlas_gpu_usage_desc(struct sg_image_usage* usage) { + wayc_notnull(usage); + + usage->immutable = false; + usage->dynamic_update = true; +} + +static void wayc_atlas_gpu_desc(struct sg_image_desc* desc, u32 width, + u32 height, enum sg_pixel_format format) { + wayc_notnull(desc); + + struct sg_image_usage usage = {}; + wayc_atlas_gpu_usage_desc(&usage); + + desc->type = SG_IMAGETYPE_2D; + desc->width = width; + desc->height = height; + desc->num_mipmaps = 1; + desc->pixel_format = format; + desc->usage = usage; +} + +static inline usize wayc_atlas_size(struct atlas_s* atlas) { + wayc_notnull(atlas); + return atlas->width * atlas->height; +} + +enum atlas_error_e wayc_atlas_init(struct atlas_s* atlas, u32 width, u32 height, + enum sg_pixel_format format) { + wayc_notnull(atlas); + + bool success = false; + + usize atlas_size = wayc_atlas_size(atlas); + u8* cpu_atlas = (u8*)mi_malloc(atlas_size); + wayc_defer_cond(mi_free(cpu_atlas);, success, true); + + struct sg_image_desc desc = {}; + wayc_atlas_gpu_desc(&desc, width, height, format); + + struct sg_image gpu_atlas = sg_make_image(&desc); + if (sg_query_image_state(gpu_atlas) != SG_RESOURCESTATE_VALID) + return ATLAS_ERROR_GPU_ATLAS; + + atlas->width = width; + atlas->height = height; + atlas->cpu_atlas = cpu_atlas; + atlas->gpu_atlas = gpu_atlas; + atlas->cpu_dirty = false; + + success = true; + return ATLAS_ERROR_NONE; +} + +enum atlas_error_e wayc_atlas_flush(struct atlas_s* atlas) { + wayc_notnull(atlas); + if (!atlas->cpu_dirty) return ATLAS_ERROR_NONE; + + struct sg_range range = {}; + range.ptr = atlas->cpu_atlas; + range.size = wayc_atlas_size(atlas); + + struct sg_image_data data = {}; + data.mip_levels[0] = range; + + sg_update_image(atlas->gpu_atlas, &data); + if (sg_query_image_state(atlas->gpu_atlas) != SG_RESOURCESTATE_VALID) + return ATLAS_ERROR_UPLOAD_FAILED; + + atlas->cpu_dirty = false; + return ATLAS_ERROR_NONE; +} + +void wayc_atlas_deinit(struct atlas_s* atlas) { + wayc_notnull(atlas); + + enum sg_resource_state state = sg_query_image_state(atlas->gpu_atlas); + if (atlas->cpu_atlas == nullptr || state != SG_RESOURCESTATE_VALID) return; + + sg_destroy_image(atlas->gpu_atlas); + mi_free(atlas->cpu_atlas); + + atlas->width = 0; + atlas->height = 0; + atlas->cpu_atlas = nullptr; + atlas->gpu_atlas = {}; +} diff --git a/src/atlas.h b/src/atlas.h new file mode 100644 index 0000000..be10c3b --- /dev/null +++ b/src/atlas.h @@ -0,0 +1,23 @@ +#pragma once + +#include "sokol_gfx.h" +#include "utils.h" + +enum atlas_error_e : u8 { + ATLAS_ERROR_NONE = 0, + ATLAS_ERROR_GPU_ATLAS, + ATLAS_ERROR_ATLAS_FULL, + ATLAS_ERROR_UPLOAD_FAILED, +}; + +struct atlas_s { + u32 width, height; + struct sg_image gpu_atlas; + u8* cpu_atlas; + bool cpu_dirty; +}; + +enum atlas_error_e wayc_atlas_init(struct atlas_s* atlas, u32 width, u32 height, + enum sg_pixel_format format); +enum atlas_error_e wayc_atlas_flush(struct atlas_s* atlas); +void wayc_atlas_deinit(struct atlas_s* atlas); diff --git a/src/text.cc b/src/text.cc index 58fedad..ab2155f 100644 --- a/src/text.cc +++ b/src/text.cc @@ -2,11 +2,12 @@ #include <cstddef> +#include "atlas.h" #include "freetype/freetype.h" #include "shaders.h" #include "utils.h" -static void font_context_sampler_desc(struct sg_sampler_desc* desc) { +static void wayc_font_context_sampler_desc(struct sg_sampler_desc* desc) { wayc_notnull(desc); desc->min_filter = SG_FILTER_LINEAR; @@ -15,7 +16,7 @@ static void font_context_sampler_desc(struct sg_sampler_desc* desc) { desc->wrap_v = SG_WRAP_CLAMP_TO_EDGE; } -static void font_context_layout(struct sg_vertex_layout_state* layout) { +static void wayc_font_context_layout(struct sg_vertex_layout_state* layout) { wayc_notnull(layout); layout->buffers[0].stride = sizeof(text_vertex_s); @@ -29,7 +30,7 @@ static void font_context_layout(struct sg_vertex_layout_state* layout) { layout->attrs[ATTR_text_in_uv].offset = offsetof(text_vertex_s, uv); } -static void font_context_color(struct sg_color_target_state* color) { +static void wayc_font_context_color(struct sg_color_target_state* color) { wayc_notnull(color); struct sg_blend_state blend = {}; @@ -42,18 +43,15 @@ static void font_context_color(struct sg_color_target_state* color) { color->blend = blend; } -static void font_context_pipeline_desc(struct sg_pipeline_desc* desc) { +static void font_context_pipeline_desc(struct sg_pipeline_desc* desc, + struct sg_shader shader) { wayc_notnull(desc); - const struct sg_shader_desc* shader_desc = - text_shader_desc(sg_query_backend()); - struct sg_shader shader = sg_make_shader(shader_desc); - struct sg_vertex_layout_state vertex_layout = {}; - font_context_layout(&vertex_layout); + wayc_font_context_layout(&vertex_layout); struct sg_color_target_state color = {}; - font_context_color(&color); + wayc_font_context_color(&color); desc->layout = vertex_layout; desc->shader = shader; @@ -62,27 +60,49 @@ static void font_context_pipeline_desc(struct sg_pipeline_desc* desc) { desc->color_count = 1; } -enum font_context_error_e font_context_init(struct font_context_s* context) { +enum font_context_error_e wayc_font_context_init( + struct font_context_s* context) { wayc_notnull(context); + bool success = false; + FT_Library ft; FT_Error fterr = FT_Init_FreeType(&ft); if (fterr) return FONT_CONTEXT_ERROR_LOAD_LIBRARY; + wayc_defer_cond(FT_Done_FreeType(ft), success, true); + + struct sg_shader shader = + sg_make_shader(text_shader_desc(sg_query_backend())); + if (sg_query_shader_state(shader) != SG_RESOURCESTATE_VALID) + return FONT_CONTEXT_ERROR_CREATE_SHADER; + wayc_defer_cond(sg_destroy_shader(shader), success, true); struct sg_sampler_desc sampler_desc = {}; - font_context_sampler_desc(&sampler_desc); + wayc_font_context_sampler_desc(&sampler_desc); struct sg_pipeline_desc pipeline_desc = {}; - font_context_pipeline_desc(&pipeline_desc); + font_context_pipeline_desc(&pipeline_desc, shader); + + struct sg_sampler sampler = sg_make_sampler(&sampler_desc); + if (sg_query_sampler_state(sampler) != SG_RESOURCESTATE_VALID) + return FONT_CONTEXT_ERROR_CREATE_SAMPLER; + + wayc_defer_cond(sg_destroy_sampler(sampler), success, true); + + struct sg_pipeline pipeline = sg_make_pipeline(&pipeline_desc); + if (sg_query_pipeline_state(pipeline) != SG_RESOURCESTATE_VALID) + return FONT_CONTEXT_ERROR_CREATE_PIPELINE; context->ft = ft; - context->sampler = sg_make_sampler(&sampler_desc); - context->pipeline = sg_make_pipeline(&pipeline_desc); + context->sampler = sampler; + context->pipeline = pipeline; + + success = true; return FONT_CONTEXT_ERROR_NONE; } -void font_context_deinit(struct font_context_s* context) { +void wayc_font_context_deinit(struct font_context_s* context) { wayc_notnull(context); sg_destroy_pipeline(context->pipeline); @@ -1,5 +1,6 @@ #pragma once +#include "atlas.h" #include "cglm/types.h" #include "freetype/freetype.h" #include "sokol_gfx.h" @@ -13,6 +14,9 @@ struct text_vertex_s { enum font_context_error_e : u8 { FONT_CONTEXT_ERROR_NONE = 0, FONT_CONTEXT_ERROR_LOAD_LIBRARY, + FONT_CONTEXT_ERROR_CREATE_SAMPLER, + FONT_CONTEXT_ERROR_CREATE_SHADER, + FONT_CONTEXT_ERROR_CREATE_PIPELINE, }; struct font_context_s { @@ -21,14 +25,24 @@ struct font_context_s { struct sg_sampler sampler; }; -enum font_context_error_e font_context_init(struct font_context_s* context); -void font_context_deinit(struct font_context_s* context); +enum font_context_error_e wayc_font_context_init( + struct font_context_s* context); +void wayc_font_context_deinit(struct font_context_s* context); + +enum font_error_e : u8 { + FONT_ERROR_NONE = 0, + FONT_ERROR_LOAD_FACE, + +}; struct font_s { FT_Face face; + u32 font_size; u8* source; - u8* staging; - bool staging_dirty; - struct sg_image atlas; + struct atlas_s atlas; }; + +enum font_error_e wayc_font_init(struct font_s* font, + struct font_context_s* context, + const char* path, u32 font_size);
\ No newline at end of file |
