diff --git a/src/rendering/twn_gl_any_rendering.c b/src/rendering/twn_gl_any_rendering.c index 8d08831..8f16e8a 100644 --- a/src/rendering/twn_gl_any_rendering.c +++ b/src/rendering/twn_gl_any_rendering.c @@ -119,11 +119,14 @@ GLuint get_scratch_vertex_array(void) { } -GPUTexture create_gpu_texture(TextureFilter filter, bool generate_mipmaps) { +GPUTexture create_gpu_texture(TextureFilter filter, bool generate_mipmaps, int channels, int width, int height) { GLuint texture; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); + SDL_assert(width > 0 && height > 0); + SDL_assert(channels > 0 && channels <= 4); + #if !defined(EMSCRIPTEN) glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, (GLboolean)generate_mipmaps); #else @@ -146,19 +149,6 @@ GPUTexture create_gpu_texture(TextureFilter filter, bool generate_mipmaps) { glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); #endif - glBindTexture(GL_TEXTURE_2D, 0); - return texture; -} - - -void delete_gpu_texture(GPUTexture texture) { - glDeleteTextures(1, &texture); -} - - -void upload_gpu_texture(GPUTexture texture, void *pixels, int channels, int width, int height) { - glBindTexture(GL_TEXTURE_2D, texture); - int format_internal, format; if (channels == 4) { #ifdef EMSCRIPTEN @@ -179,9 +169,11 @@ void upload_gpu_texture(GPUTexture texture, void *pixels, int channels, int widt format = GL_ALPHA; } else { CRY("upload_gpu_texture", "Unsupported channel count"); - return; + format_internal = GL_ALPHA; + format = GL_ALPHA; } + /* preallocate texture storage in advance */ glTexImage2D(GL_TEXTURE_2D, 0, format_internal, @@ -190,7 +182,46 @@ void upload_gpu_texture(GPUTexture texture, void *pixels, int channels, int widt 0, format, GL_UNSIGNED_BYTE, - pixels); + NULL); + + glBindTexture(GL_TEXTURE_2D, 0); + return texture; +} + + +void delete_gpu_texture(GPUTexture texture) { + glDeleteTextures(1, &texture); +} + + +void upload_gpu_texture(GPUTexture texture, void *pixels, int channels, int width, int height) { + glBindTexture(GL_TEXTURE_2D, texture); + + int format; + if (channels == 4) { + format = GL_RGBA; + } else if (channels == 3) { + format = GL_RGB; + } else if (channels == 1) { + format = GL_ALPHA; + } else { + CRY("upload_gpu_texture", "Unsupported channel count"); + return; + } + + profile_start("texture upload"); + + glTexSubImage2D(GL_TEXTURE_2D, + 0, + 0, + 0, + width, + height, + format, + GL_UNSIGNED_BYTE, + pixels); + + profile_end("texture upload"); glBindTexture(GL_TEXTURE_2D, 0); } diff --git a/src/rendering/twn_gpu_texture_c.h b/src/rendering/twn_gpu_texture_c.h index 962f41a..91add2e 100644 --- a/src/rendering/twn_gpu_texture_c.h +++ b/src/rendering/twn_gpu_texture_c.h @@ -11,7 +11,8 @@ typedef enum TextureFilter { TEXTURE_FILTER_LINEAR, } TextureFilter; -GPUTexture create_gpu_texture(TextureFilter filter, bool generate_mipmaps); +/* allocate a texture storage with constant parameters */ +GPUTexture create_gpu_texture(TextureFilter filter, bool generate_mipmaps, int channels, int width, int height); void delete_gpu_texture(GPUTexture texture); diff --git a/src/rendering/twn_text.c b/src/rendering/twn_text.c index e5bfe5f..a00b6f8 100644 --- a/src/rendering/twn_text.c +++ b/src/rendering/twn_text.c @@ -150,7 +150,7 @@ static FontData *text_load_font_data(const char *path, int height_px) { stbtt_PackEnd(&pctx); } - font_data->texture = create_gpu_texture(ctx.font_filtering, true); + font_data->texture = create_gpu_texture(ctx.font_filtering, true, 1, (int)ctx.font_texture_size, (int)ctx.font_texture_size); upload_gpu_texture( font_data->texture, bitmap, diff --git a/src/twn_textures.c b/src/twn_textures.c index 27b8988..0581753 100644 --- a/src/twn_textures.c +++ b/src/twn_textures.c @@ -193,7 +193,7 @@ static SDL_Surface *create_surface(int width, int height) { static void add_new_atlas(TextureCache *cache) { SDL_Surface *new_atlas = create_surface((int)ctx.texture_atlas_size, (int)ctx.texture_atlas_size); arrput(cache->atlas_surfaces, new_atlas); - arrput(cache->atlas_textures, create_gpu_texture(TEXTURE_FILTER_NEAREAST, true)); + arrput(cache->atlas_textures, create_gpu_texture(TEXTURE_FILTER_NEAREAST, true, 4, (int)ctx.texture_atlas_size, (int)ctx.texture_atlas_size)); } @@ -510,7 +510,7 @@ void textures_update_atlas(TextureCache *cache) { if (!is_power_of_two(response.data->w) || !is_power_of_two(response.data->h)) log_warn("Unportable texture dimensions for %s, should be powers of 2", cache->hash[texture_load_queue[i].index].key); } - response.loner_texture = create_gpu_texture(TEXTURE_FILTER_NEAREAST, true); + response.loner_texture = create_gpu_texture(TEXTURE_FILTER_NEAREAST, true, response.data->format->BytesPerPixel, response.data->w, response.data->h); upload_texture_from_surface(response.loner_texture, response.data); response.srcrect = (Rect) { .w = (float)response.data->w, .h = (float)response.data->h }; @@ -642,7 +642,11 @@ void textures_bind_repeating(const TextureCache *cache, TextureKey key) { const Texture texture = cache->hash[key.id].value; - const GPUTexture repeating_texture = create_gpu_texture(TEXTURE_FILTER_NEAREAST, false); + const GPUTexture repeating_texture = create_gpu_texture(TEXTURE_FILTER_NEAREAST, + false, + texture.data->format->BytesPerPixel, + texture.data->w, + texture.data->h); SDL_LockSurface(texture.data);