full removal of SDL_Renderer usage, working spatial triangle rendering, temporary(?) regression of HDPI
This commit is contained in:
120
src/textures.c
120
src/textures.c
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user