diff --git a/src/twn_textures.c b/src/twn_textures.c index d6558d4..9be9ca4 100644 --- a/src/twn_textures.c +++ b/src/twn_textures.c @@ -41,7 +41,8 @@ static int load_eof_callback(void *user) { } -static uint8_t *missing_texture_data; +static SDL_Surface *missing_texture_surface; +static uint16_t missing_texture_id; static SDL_Surface *gen_missing_texture_surface(void) { Uint32 rmask, gmask, bmask; @@ -56,22 +57,23 @@ static SDL_Surface *gen_missing_texture_surface(void) { bmask = 0x00ff0000; #endif - if (!missing_texture_data) { - missing_texture_data = SDL_malloc(64 * 64 * 3); - for (int y = 0; y < 64; ++y) + if (!missing_texture_surface) { + uint8_t *data = SDL_malloc(64 * 64 * 3); + for (int y = 0; y < 64; ++y) { for (int x = 0; x < 64; ++x) { /* diagonal stripes, chosen so that asked pixel uvs are corresponding to final output */ - missing_texture_data[(y * 64 + x) * 3 + 0] = (x / 2 + y / 2) % 2 == 0 ? 175 : 0; - missing_texture_data[(y * 64 + x) * 3 + 1] = (x / 2 + y / 2) % 2 == 0 ? 0 : 0; - missing_texture_data[(y * 64 + x) * 3 + 2] = (x / 2 + y / 2) % 2 == 0 ? 175 : 0; + data[(y * 64 + x) * 3 + 0] = (x / 2 + y / 2) % 2 == 0 ? 175 : 0; + data[(y * 64 + x) * 3 + 1] = (x / 2 + y / 2) % 2 == 0 ? 0 : 0; + data[(y * 64 + x) * 3 + 2] = (x / 2 + y / 2) % 2 == 0 ? 175 : 0; } + } + + missing_texture_surface = SDL_CreateRGBSurfaceFrom(data, 64, 64, + 3 * 8, + 64 * 3, + rmask, gmask, bmask, 0); } - /* same data is reused after being allocated/generated once */ - SDL_Surface *missing_texture_surface = SDL_CreateRGBSurfaceFrom(missing_texture_data, 64, 64, - 3 * 8, - 64 * 3, - rmask, gmask, bmask, 0); return missing_texture_surface; } @@ -327,8 +329,10 @@ void textures_cache_deinit(TextureCache *cache) { /* free cache hashes */ for (size_t i = 0; i < shlenu(cache->hash); ++i) { - if (cache->hash[i].value.data->pixels != missing_texture_data) + if (missing_texture_surface && cache->hash[i].value.data->pixels != missing_texture_surface->pixels) stbi_image_free(cache->hash[i].value.data->pixels); + else + SDL_free(cache->hash[i].value.data->pixels); SDL_FreeSurface(cache->hash[i].value.data); } shfree(cache->hash); @@ -372,6 +376,9 @@ static TextureKey textures_load(TextureCache *cache, const char *path) { return (TextureKey){ (uint16_t)i }; SDL_Surface *surface = textures_load_surface(path); + if (surface == missing_texture_surface && missing_texture_id != 0) + return (TextureKey){ missing_texture_id }; + Texture new_texture = { .data = surface, .mode = infer_texture_mode(surface), @@ -388,13 +395,22 @@ static TextureKey textures_load(TextureCache *cache, const char *path) { new_texture.loner_texture = create_gpu_texture(TEXTURE_FILTER_NEAREAST, true); upload_texture_from_surface(new_texture.loner_texture, surface); new_texture.srcrect = (Rect) { .w = (float)surface->w, .h = (float)surface->h }; + } else { /* will be fully populated as the atlas updates */ new_texture.atlas_index = cache->atlas_index; cache->is_dirty = true; } + shput(cache->hash, path, new_texture); - return (TextureKey){ (uint16_t)shgeti(cache->hash, path) }; + + uint16_t const id = (uint16_t)shgeti(cache->hash, path); + + /* reuse this id for every later missing texture */ + if (surface == missing_texture_surface) + missing_texture_id = id; + + return (TextureKey){ id }; }