summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--src/atlas.cc92
-rw-r--r--src/atlas.h23
-rw-r--r--src/text.cc52
-rw-r--r--src/text.h24
5 files changed, 171 insertions, 21 deletions
diff --git a/Makefile b/Makefile
index 294c8a7..115a6d9 100644
--- a/Makefile
+++ b/Makefile
@@ -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);
diff --git a/src/text.h b/src/text.h
index 2e768ee..e1a8b3d 100644
--- a/src/text.h
+++ b/src/text.h
@@ -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