full removal of SDL_Renderer usage, working spatial triangle rendering, temporary(?) regression of HDPI

This commit is contained in:
2024-07-12 21:10:25 +03:00
parent 34cf504b2b
commit 55d85399e9
12 changed files with 348 additions and 224 deletions

View File

@@ -1,6 +1,7 @@
#include "textures.h"
#include "private/textures.h"
#include "config.h"
#include "util.h"
#include "textures.h"
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
@@ -35,6 +36,24 @@ fail:
}
static GLuint new_gl_texture(void) {
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glBindTexture(GL_TEXTURE_2D, 0);
return texture;
}
/* adds a new, blank atlas surface to the cache */
static void add_new_atlas(struct texture_cache *cache) {
SDL_PixelFormat *native_format =
@@ -57,12 +76,51 @@ static void add_new_atlas(struct texture_cache *cache) {
a_mask);
SDL_FreeFormat(native_format);
SDL_SetSurfaceRLE(new_atlas, true);
SDL_SetSurfaceRLE(new_atlas, true);
arrput(cache->atlas_surfaces, new_atlas);
SDL_Texture *new_atlas_texture =
SDL_CreateTextureFromSurface(cache->renderer, new_atlas);
arrput(cache->atlas_textures, new_atlas_texture);
arrput(cache->atlas_textures, new_gl_texture());
}
static void upload_texture_from_surface(GLuint texture, SDL_Surface *surface) {
Uint32 rmask, gmask, bmask, amask;
glBindTexture(GL_TEXTURE_2D, texture);
// glPixelStorei(GL_PACK_ALIGNMENT, 1);
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
rmask = 0xff000000;
gmask = 0x00ff0000;
bmask = 0x0000ff00;
amask = 0x000000ff;
#else
rmask = 0x000000ff;
gmask = 0x0000ff00;
bmask = 0x00ff0000;
amask = 0xff000000;
#endif
/* TODO: don't do it if format is compatible */
SDL_Surface* intermediate = SDL_CreateRGBSurface(0,
surface->w, surface->h, 32, rmask, gmask, bmask, amask);
SDL_BlitSurface(surface, NULL, intermediate, NULL);
SDL_LockSurface(intermediate);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA,
surface->w,
surface->h,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
intermediate->pixels);
SDL_UnlockSurface(intermediate);
SDL_FreeSurface(intermediate);
glBindTexture(GL_TEXTURE_2D, 0);
}
@@ -85,12 +143,7 @@ static void recreate_current_atlas_texture(struct texture_cache *cache) {
}
/* texturize it! */
SDL_LockSurface(atlas_surface);
SDL_UpdateTexture(cache->atlas_textures[cache->atlas_index],
NULL,
atlas_surface->pixels,
atlas_surface->pitch);
SDL_UnlockSurface(atlas_surface);
upload_texture_from_surface(cache->atlas_textures[cache->atlas_index], atlas_surface);
}
@@ -171,7 +224,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;
cache->renderer = SDL_GetRenderer(window);
sh_new_arena(cache->hash);
sh_new_arena(cache->loner_hash);
@@ -185,7 +237,7 @@ void textures_cache_init(struct texture_cache *cache, SDL_Window *window) {
void textures_cache_deinit(struct texture_cache *cache) {
/* free atlas textures */
for (size_t i = 0; i < arrlenu(cache->atlas_textures); ++i) {
SDL_DestroyTexture(cache->atlas_textures[i]);
glDeleteTextures(1, &cache->atlas_textures[i]);
}
arrfree(cache->atlas_textures);
@@ -247,8 +299,11 @@ void textures_load(struct texture_cache *cache, const char *path) {
/* 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 = SDL_CreateTextureFromSurface(cache->renderer, surface);
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);
} else {
new_texture.atlas_index = cache->atlas_index;
@@ -301,17 +356,23 @@ void textures_update_current_atlas(struct texture_cache *cache) {
SDL_Rect textures_get_srcrect(struct texture_cache *cache, const char *path) {
struct texture_cache_item *texture = shgetp_null(cache->hash, path);
if (texture == NULL) {
int index = textures_get_atlas_index(cache, path);
if (index == -1) {
return shget(cache->loner_hash, path).srcrect;
} else if (index == INT_MIN) {
CRY("Texture lookup failed.",
"Tried to get texture that isn't loaded.");
return (SDL_Rect){ 0, 0, 0, 0 };
} else {
return shget(cache->hash, path).srcrect;
}
return texture->value.srcrect;
}
/* 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);
@@ -331,25 +392,28 @@ int textures_get_atlas_index(struct texture_cache *cache, const char *path) {
}
SDL_Texture *textures_get_atlas(struct texture_cache *cache, int 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)
return NULL;
if (arrlen(cache->atlas_textures) < index + 1 || index < 0) {
CRY("Atlas texture binding failed.",
"Tried to bind texture by invalid index");
return;
}
return cache->atlas_textures[index];
glBindTexture(target, cache->atlas_textures[index]);
}
SDL_Texture *textures_get_loner(struct texture_cache *cache, const char *path) {
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 lookup failed.",
"Tried to get texture that isn't loaded.");
return NULL;
CRY("Loner texture binding failed.",
"Tried to bind texture that isn't loaded.");
return;
}
return texture->value.loner_data;
glBindTexture(target, texture->value.loner_data);
}