summaryrefslogtreecommitdiff
path: root/src/atlas.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/atlas.cc')
-rw-r--r--src/atlas.cc92
1 files changed, 92 insertions, 0 deletions
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 = {};
+}