--- deliantra/Deliantra-Client/texcache.c 2006/07/04 23:23:32 1.1 +++ deliantra/Deliantra-Client/texcache.c 2018/11/18 00:52:22 1.9 @@ -1,4 +1,5 @@ // all these must be powers of two +// width and height better be <=256 as we use bytes in the rendercache #define TC_WIDTH 256 #define TC_HEIGHT 256 #define TC_ROUND 4 @@ -8,18 +9,28 @@ int x, y, w, h; } tc_area; -void tc_get (tc_area *area, int width, int height); -void tc_put (tc_area *area); -void tc_clear (); +extern int tc_generation; + +static void tc_get (tc_area *area, int width, int height); +static void tc_put (tc_area *area); +static void tc_clear (void); +static void tc_backup (void); +static void tc_restore (void); ///////////////////////////////////////////////////////////////////////////// +// required as bug-workaround for apple/ati/... +static unsigned char tc_temptile [TC_WIDTH * TC_HEIGHT]; + #include +int tc_generation; + typedef struct tc_texture { struct tc_texture *next; GLuint name; int avail; + char *saved; /* stores saved texture data */ } tc_texture; typedef struct tc_slice { @@ -31,7 +42,7 @@ static tc_texture *first_texture; void -tc_clear () +tc_clear (void) { int i; @@ -41,10 +52,51 @@ while (first_texture) { tc_texture *next = first_texture->next; - glDeleteTextures (1, &first_texture->name); + del_texture (first_texture->name); g_slice_free (tc_texture, first_texture); first_texture = next; } + + ++tc_generation; +} + +void +tex_backup (tc_texture *tex) +{ + tex->saved = (char *)g_slice_alloc (TC_WIDTH * TC_HEIGHT); + + glBindTexture (GL_TEXTURE_2D, tex->name); + glGetTexImage (GL_TEXTURE_2D, 0, GL_ALPHA, GL_UNSIGNED_BYTE, tex->saved); +} + +void +tex_restore (tc_texture *tex) +{ + glBindTexture (GL_TEXTURE_2D, tex->name); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexImage2D (GL_TEXTURE_2D, 0, GL_ALPHA, TC_WIDTH, TC_HEIGHT, 0, GL_ALPHA, GL_UNSIGNED_BYTE, tex->saved); + + g_slice_free1 (TC_WIDTH * TC_HEIGHT, tex->saved); + tex->saved = 0; +} + +void +tc_backup (void) +{ + tc_texture *tex; + + for (tex = first_texture; tex; tex = tex->next) + tex_backup (tex); +} + +void +tc_restore (void) +{ + tc_texture *tex; + + for (tex = first_texture; tex; tex = tex->next) + tex_restore (tex); } void @@ -71,15 +123,23 @@ if (!match) { match = g_slice_new (tc_texture); - match->next = first_texture; + match->next = first_texture; first_texture = match; - glGenTextures (1, &match->name); - match->avail = TC_HEIGHT; + match->name = gen_texture (); + match->avail = TC_HEIGHT; + match->saved = 0; glBindTexture (GL_TEXTURE_2D, match->name); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexImage2D (GL_TEXTURE_2D, 0, GL_ALPHA, TC_WIDTH, TC_HEIGHT, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0); + + // the last parameter should be NULL, but way too amny drivers (ATI, Mesa) crash, + // so we better provide some random garbage data for them. + glTexImage2D (GL_TEXTURE_2D, + 0, GL_ALPHA, + TC_WIDTH, TC_HEIGHT, + 0, GL_ALPHA, + GL_UNSIGNED_BYTE, tc_temptile); } match->avail -= slice_height;