twn_textures.c: make missing texture single and reused
This commit is contained in:
		@@ -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) {
 | 
					static SDL_Surface *gen_missing_texture_surface(void) {
 | 
				
			||||||
    Uint32 rmask, gmask, bmask;
 | 
					    Uint32 rmask, gmask, bmask;
 | 
				
			||||||
@@ -56,22 +57,23 @@ static SDL_Surface *gen_missing_texture_surface(void) {
 | 
				
			|||||||
        bmask = 0x00ff0000;
 | 
					        bmask = 0x00ff0000;
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!missing_texture_data) {
 | 
					    if (!missing_texture_surface) {
 | 
				
			||||||
        missing_texture_data = SDL_malloc(64 * 64 * 3);
 | 
					        uint8_t *data = SDL_malloc(64 * 64 * 3);
 | 
				
			||||||
        for (int y = 0; y < 64; ++y)
 | 
					        for (int y = 0; y < 64; ++y) {
 | 
				
			||||||
            for (int x = 0; x < 64; ++x) {
 | 
					            for (int x = 0; x < 64; ++x) {
 | 
				
			||||||
                /* diagonal stripes, chosen so that asked pixel uvs are corresponding to final output */
 | 
					                /* 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;
 | 
					                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;
 | 
					                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 + 2] = (x / 2 + y / 2) % 2 == 0 ? 175 : 0;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* same data is reused after being allocated/generated once */
 | 
					        missing_texture_surface = SDL_CreateRGBSurfaceFrom(data, 64, 64,
 | 
				
			||||||
    SDL_Surface *missing_texture_surface = SDL_CreateRGBSurfaceFrom(missing_texture_data, 64, 64,
 | 
					 | 
				
			||||||
                                                           3 * 8,
 | 
					                                                           3 * 8,
 | 
				
			||||||
                                                           64 * 3,
 | 
					                                                           64 * 3,
 | 
				
			||||||
                                                           rmask, gmask, bmask, 0);
 | 
					                                                           rmask, gmask, bmask, 0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return missing_texture_surface;
 | 
					    return missing_texture_surface;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -327,8 +329,10 @@ void textures_cache_deinit(TextureCache *cache) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /* free cache hashes */
 | 
					    /* free cache hashes */
 | 
				
			||||||
    for (size_t i = 0; i < shlenu(cache->hash); ++i) {
 | 
					    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);
 | 
					            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);
 | 
					        SDL_FreeSurface(cache->hash[i].value.data);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    shfree(cache->hash);
 | 
					    shfree(cache->hash);
 | 
				
			||||||
@@ -372,6 +376,9 @@ static TextureKey textures_load(TextureCache *cache, const char *path) {
 | 
				
			|||||||
        return (TextureKey){ (uint16_t)i };
 | 
					        return (TextureKey){ (uint16_t)i };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    SDL_Surface *surface = textures_load_surface(path);
 | 
					    SDL_Surface *surface = textures_load_surface(path);
 | 
				
			||||||
 | 
					    if (surface == missing_texture_surface && missing_texture_id != 0)
 | 
				
			||||||
 | 
					        return (TextureKey){ missing_texture_id };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Texture new_texture = {
 | 
					    Texture new_texture = {
 | 
				
			||||||
        .data = surface,
 | 
					        .data = surface,
 | 
				
			||||||
        .mode = infer_texture_mode(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);
 | 
					        new_texture.loner_texture = create_gpu_texture(TEXTURE_FILTER_NEAREAST, true);
 | 
				
			||||||
        upload_texture_from_surface(new_texture.loner_texture, surface); 
 | 
					        upload_texture_from_surface(new_texture.loner_texture, surface); 
 | 
				
			||||||
        new_texture.srcrect = (Rect) { .w = (float)surface->w, .h = (float)surface->h };
 | 
					        new_texture.srcrect = (Rect) { .w = (float)surface->w, .h = (float)surface->h };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        /* will be fully populated as the atlas updates */
 | 
					        /* will be fully populated as the atlas updates */
 | 
				
			||||||
        new_texture.atlas_index = cache->atlas_index;
 | 
					        new_texture.atlas_index = cache->atlas_index;
 | 
				
			||||||
        cache->is_dirty = true;
 | 
					        cache->is_dirty = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    shput(cache->hash, path, new_texture);
 | 
					    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 };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user