#ifndef TWN_TEXTURES_C_H #define TWN_TEXTURES_C_H #include "twn_types.h" #include "rendering/twn_gpu_texture_c.h" #include #include #include #define TEXTURE_ATLAS_SIZE_DEFAULT 2048 #define TEXTURE_ATLAS_BIT_DEPTH 32 #define TEXTURE_ATLAS_FORMAT SDL_PIXELFORMAT_RGBA32 /* alpha channel information */ typedef enum TextureMode { TEXTURE_MODE_OPAQUE, /* all pixels are solid */ TEXTURE_MODE_SEETHROUGH, /* some pixels are alpha zero */ TEXTURE_MODE_GHOSTLY, /* arbitrary alpha values */ TEXTURE_MODE_COUNT, TEXTURE_MODE_UNKNOWN = -1, /* a sentinel */ } TextureMode; typedef struct Texture { Rect srcrect; /* position in atlas */ SDL_Surface *data; /* original image data */ int atlas_index; GPUTexture loner_texture; /* stored directly for loners, == 0 means atlas_index should be used */ GPUTexture repeating_texture; /* separately allocated Texture, for loners == loner_texture */ enum TextureMode mode; } Texture; typedef struct TextureCacheItem { char *key; struct Texture value; } TextureCacheItem; typedef struct TextureCache { SDL_Window *window; /* from context */ struct TextureCacheItem *hash; stbrp_node *node_buffer; /* used internally by stb_rect_pack */ SDL_Surface **atlas_surfaces; GPUTexture *atlas_textures; /* shared by atlas textures */ int atlas_index; /* atlas that is currently being built */ bool is_dirty; /* current atlas needs to be recreated */ } TextureCache; /* type safe structure for frame persistent texture handles */ typedef struct TextureKey { uint16_t id; } TextureKey; /* tests whether given key structure corresponds to any texture */ #define TEXTURE_KEY_INVALID (TextureKey) { (uint16_t)-1 } #define m_texture_key_is_valid(p_key) ((p_key).id != (uint16_t)-1) void textures_cache_init(struct TextureCache *cache, SDL_Window *window); void textures_cache_deinit(struct TextureCache *cache); /* repacks the current texture atlas based on the texture cache if needed */ /* any previously returned srcrect results are invalidated after that */ /* call it every time before rendering */ void textures_update_atlas(TextureCache *cache); /* returns a frame persistent handle to some texture in cache, loading it if needed */ /* check the result with m_texture_key_is_valid() */ TextureKey textures_get_key(TextureCache *cache, const char *path); /* returns a rect in a texture cache of the given key */ Rect textures_get_srcrect(const TextureCache *cache, TextureKey key); /* returns a rect of dimensions of the whole texture (whole atlas) */ Rect textures_get_dims(const TextureCache *cache, TextureKey key); /* returns an identifier that is equal for all textures placed in the same atlas */ int32_t textures_get_atlas_id(const TextureCache *cache, TextureKey key); void textures_bind(const TextureCache *cache, TextureKey key); void textures_bind_repeating(const TextureCache *cache, TextureKey key); /* returns helpful information about contents of alpha channel in given texture */ TextureMode textures_get_mode(const TextureCache *cache, TextureKey key); /* returns the number of atlases in the cache */ size_t textures_get_num_atlases(const TextureCache *cache); /* TODO: should recieve texture_cache, get_key optimization cache should be cleared some other way */ void textures_reset_state(void); /* uncached low-level loading */ /* warn: surface->pixels must be freed along side the surface itself */ SDL_Surface *textures_load_surface(const char *path); /* note: will only take an effect after `textures_update_atlas` */ bool textures_load_workers_thread(void); #endif