rework of textures, finalization of basic opengl rendering

This commit is contained in:
2024-07-14 16:04:12 +03:00
parent 55d85399e9
commit bd53a931c0
10 changed files with 243 additions and 245 deletions

View File

@@ -10,7 +10,6 @@
#include <stb_ds.h>
#include <stb_rect_pack.h>
#include <limits.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
@@ -139,7 +138,12 @@ static void recreate_current_atlas_texture(struct texture_cache *cache) {
SDL_BlitSurface(cache->hash[i].value.data,
NULL,
atlas_surface,
&cache->hash[i].value.srcrect);
&(SDL_Rect){
.x = cache->hash[i].value.srcrect.x,
.y = cache->hash[i].value.srcrect.y,
.w = cache->hash[i].value.srcrect.w,
.h = cache->hash[i].value.srcrect.h,
});
}
/* texturize it! */
@@ -212,7 +216,7 @@ static bool update_rects(struct texture_cache *cache, stbrp_rect *rects, stbrp_r
/* updates the atlas location of every rect in the cache */
static void update_texture_rects_in_atlas(struct texture_cache *cache, stbrp_rect *rects) {
for (size_t i = 0; i < arrlenu(rects); ++i) {
cache->hash[i].value.srcrect = (SDL_Rect) {
cache->hash[i].value.srcrect = (t_rect) {
.x = rects[i].x,
.y = rects[i].y,
.w = rects[i].w,
@@ -225,7 +229,6 @@ static void update_texture_rects_in_atlas(struct texture_cache *cache, stbrp_rec
void textures_cache_init(struct texture_cache *cache, SDL_Window *window) {
cache->window = window;
sh_new_arena(cache->hash);
sh_new_arena(cache->loner_hash);
cache->node_buffer = cmalloc(sizeof *cache->node_buffer * TEXTURE_ATLAS_SIZE);
@@ -253,11 +256,6 @@ void textures_cache_deinit(struct texture_cache *cache) {
}
shfree(cache->hash);
for (size_t i = 0; i < shlenu(cache->loner_hash); ++i) {
SDL_FreeSurface(cache->loner_hash[i].value.data);
}
shfree(cache->loner_hash);
free(cache->node_buffer);
}
@@ -282,38 +280,38 @@ void textures_dump_atlases(struct texture_cache *cache) {
IMG_SavePNG_RW(cache->atlas_surfaces[i], handle, true);
log_info("Dumped atlas %s", buf);
}
size_t num_loners = shlenu(cache->loner_hash);
log_info("%zd atlases dumped. %zd loners left undumped.", i, num_loners);
}
void textures_load(struct texture_cache *cache, const char *path) {
static t_texture_key textures_load(struct texture_cache *cache, const char *path) {
/* no need to do anything if it was loaded already */
if (shgeti(cache->hash, path) >= 0 || shgeti(cache->loner_hash, path) >= 0)
return;
if (shgeti(cache->hash, path) >= 0)
return (t_texture_key){0};
SDL_Surface *surface = image_to_surface(path);
struct texture new_texture;
struct texture new_texture = {0};
new_texture.data = surface;
/* it's a "loner texture," it doesn't fit in an atlas so it's not in one */
if (surface->w > TEXTURE_ATLAS_SIZE || surface->h > TEXTURE_ATLAS_SIZE) {
new_texture.loner_data = new_gl_texture();
upload_texture_from_surface(new_texture.loner_data, surface);
new_texture.atlas_index = -1;
new_texture.srcrect = (SDL_Rect) {
.w = surface->w, .h = surface->h };
shput(cache->loner_hash, path, new_texture);
new_texture.loner_texture = new_gl_texture();
upload_texture_from_surface(new_texture.loner_texture, surface);
new_texture.srcrect = (t_rect) { .w = surface->w, .h = surface->h };
shput(cache->hash, path, new_texture);
return (t_texture_key){ (int)shgeti(cache->hash, path) + 1 };
} else {
new_texture.atlas_index = cache->atlas_index;
shput(cache->hash, path, new_texture);
cache->is_dirty = true;
return (t_texture_key){ (int)shgeti(cache->hash, path) + 1 };
}
}
void textures_update_current_atlas(struct texture_cache *cache) {
void textures_update_atlas(struct texture_cache *cache) {
if (!cache->is_dirty)
return;
/* this function makes a lot more sense if you read stb_rect_pack.h */
stbrp_context pack_ctx; /* target info */
stbrp_init_target(&pack_ctx,
@@ -355,68 +353,56 @@ void textures_update_current_atlas(struct texture_cache *cache) {
}
SDL_Rect textures_get_srcrect(struct texture_cache *cache, const char *path) {
int index = textures_get_atlas_index(cache, path);
if (index == -1) {
return shget(cache->loner_hash, path).srcrect;
} else if (index == INT_MIN) {
t_texture_key textures_get_key(struct texture_cache *cache, const char *path) {
/* hash tables are assumed to be stable, so we just return indices */
ptrdiff_t texture = shgeti(cache->hash, path);
/* load it if it isn't */
if (texture == -1) {
return textures_load(cache, path);
} else
return (t_texture_key){ (int)texture + 1 };
}
t_rect textures_get_srcrect(const struct texture_cache *cache, t_texture_key key) {
if (key.id != 0) {
return cache->hash[key.id - 1].value.srcrect;
} else {
CRY("Texture lookup failed.",
"Tried to get texture that isn't loaded.");
return (SDL_Rect){ 0, 0, 0, 0 };
return (t_rect){ 0, 0, 0, 0 };
}
}
t_rect textures_get_dims(const struct texture_cache *cache, t_texture_key key) {
if (key.id != 0) {
if (cache->hash[key.id - 1].value.loner_texture != 0)
return cache->hash[key.id - 1].value.srcrect;
else
return (t_rect){ .w = TEXTURE_ATLAS_SIZE, .h = TEXTURE_ATLAS_SIZE };
} else {
return shget(cache->hash, path).srcrect;
CRY("Texture lookup failed.",
"Tried to get texture that isn't loaded.");
return (t_rect){ 0, 0, 0, 0 };
}
}
/* TODO: instead of index, return a 'key' with following encoded meaning: */
/* value of 0 - no atlas (#define NO_ATLAS (0) ?) */
/* negative value - index in loners (-key - 1) */
/* positive value - index in atlases (key - 1) */
int textures_get_atlas_index(struct texture_cache *cache, const char *path) {
struct texture_cache_item *texture = shgetp_null(cache->hash, path);
/* it might be a loner texture */
if (texture == NULL) {
texture = shgetp_null(cache->loner_hash, path);
/* never mind it's just not there at all */
if (texture == NULL) {
CRY("Texture atlas index lookup failed.",
"Tried to get atlas index of texture that isn't loaded.");
return INT_MIN;
}
void textures_bind(const struct texture_cache *cache, t_texture_key key, GLenum target) {
if (key.id != 0) {
if (cache->hash[key.id - 1].value.loner_texture == 0)
glBindTexture(target, cache->atlas_textures[cache->hash[key.id - 1].value.atlas_index]);
else
glBindTexture(target, cache->hash[key.id - 1].value.loner_texture);
} else if (key.id == 0) {
CRY("Texture binding failed.",
"Tried to get texture that isn't loaded.");
}
return texture->value.atlas_index;
}
void textures_bind_atlas(struct texture_cache *cache, int index, GLenum target) {
/* out of bounds */
if (arrlen(cache->atlas_textures) < index + 1 || index < 0) {
CRY("Atlas texture binding failed.",
"Tried to bind texture by invalid index");
return;
}
glBindTexture(target, cache->atlas_textures[index]);
}
void textures_bind_loner(struct texture_cache *cache, const char *path, GLenum target) {
struct texture_cache_item *texture = shgetp_null(cache->loner_hash, path);
if (texture == NULL) {
CRY("Loner texture binding failed.",
"Tried to bind texture that isn't loaded.");
return;
}
glBindTexture(target, texture->value.loner_data);
}
size_t textures_get_num_atlases(struct texture_cache *cache) {
size_t textures_get_num_atlases(const struct texture_cache *cache) {
return cache->atlas_index + 1;
}