#include "rendering.h" #include #include #include "cglm/types.h" #include "utils.h" bool wayc_image_init(texture_t* texture, image_type_e type, image_format_e format, u32 width, u32 height) { wayc_notnull(texture); glCreateTextures(type, 1, texture); if (*texture == 0) return false; switch (type) { case IMAGE_TYPE_2D: // TODO: add error checking glTextureStorage2D(*texture, 1, format, width, height); break; default: break; } return true; } bool wayc_image_upload(texture_t texture, ivec2 offset, u32 width, u32 height, image_type_e type, image_format_e format, image_data_type_e data_type, i32 alignment, const u8* data) { wayc_notnull(data); glPixelStorei(GL_UNPACK_ALIGNMENT, alignment); switch (type) { case IMAGE_TYPE_2D: // TODO: add error checking glTextureSubImage2D(texture, 0, offset[0], offset[1], width, height, format, data_type, data); break; default: break; } return true; } void wayc_image_use(texture_t texture, u32 slot) { glBindTextureUnit(slot, texture); } void wayc_image_deinit(texture_t* texture) { wayc_notnull(texture); glDeleteTextures(1, texture); } bool wayc_sampler_init(sampler_t* sampler, sample_filter_e filter, sample_wrap_e wrap) { wayc_notnull(sampler); glCreateSamplers(1, sampler); if (*sampler == 0) return false; glSamplerParameteri(*sampler, GL_TEXTURE_MIN_FILTER, filter); glSamplerParameteri(*sampler, GL_TEXTURE_MAG_FILTER, filter); glSamplerParameteri(*sampler, GL_TEXTURE_WRAP_S, wrap); glSamplerParameteri(*sampler, GL_TEXTURE_WRAP_T, wrap); return true; } void wayc_sampler_use(sampler_t sampler, u32 slot) { glBindSampler(slot, sampler); } void wayc_sampler_deinit(sampler_t* sampler) { glDeleteSamplers(1, sampler); } bool wayc_atlas_init(atlas_s* atlas, image_format_e format, u32 width, u32 height) { wayc_notnull(atlas); memset(atlas, 0, sizeof(*atlas)); bool success = false; texture_t texture; bool ok = wayc_image_init(&texture, IMAGE_TYPE_2D, format, width, height); if (!ok) return false; wayc_defer_cond(wayc_image_deinit(&texture);, success, true); sampler_t sampler; ok = wayc_sampler_init(&sampler, SAMPLE_FILTER_NEAREST, SAMPLE_WRAP_CLAMP_TO_EDGE); if (!ok) return false; atlas->texture = texture; atlas->sampler = sampler; atlas->width = width; atlas->height = height; success = true; return true; } void wayc_atlas_use(atlas_s* atlas, u32 slot) { wayc_image_use(atlas->texture, slot); wayc_sampler_use(atlas->sampler, slot); } bool wayc_atlas_set(atlas_s* atlas, image_data_type_e data_type, ivec2 offset, u32 width, u32 height, i32 alignment, const u8* data) { wayc_notnull(atlas); wayc_notnull(data); u32 final_x = offset[0] + width; u32 final_y = offset[1] + height; if (final_x > atlas->width || final_y > atlas->height) return false; wayc_image_upload(atlas->texture, offset, width, height, IMAGE_TYPE_2D, atlas->format, data_type, alignment, data); return true; } void wayc_atlas_deinit(atlas_s* atlas) { wayc_notnull(atlas); wayc_sampler_deinit(&atlas->sampler); wayc_image_deinit(&atlas->texture); } static inline void wayc_atlas_packer_wrap(struct atlas_packer_s* packer) { WAYC_X(packer->cursor) = 0; WAYC_Y(packer->cursor) += packer->row_height; packer->row_height = 0; } bool wayc_atlas_packer_allocate(struct atlas_packer_s* packer, u32 width, u32 height, ivec2 out) { wayc_notnull(packer); struct atlas_s* atlas = packer->atlas; wayc_notnull(atlas); if (width > atlas->width || height > atlas->height) return false; if (WAYC_X(packer->cursor) + width > atlas->width) wayc_atlas_packer_wrap(packer); if (WAYC_Y(packer->cursor) + height > atlas->height) return false; glm_ivec2_copy(packer->cursor, out); WAYC_X(packer->cursor) += width; packer->row_height = wayc_max(packer->row_height, height); return true; }