--- deliantra/Deliantra-Client/texcache.c 2007/04/27 21:27:51 1.3 +++ deliantra/Deliantra-Client/texcache.c 2009/11/29 14:45:12 1.8 @@ -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 @@ -10,12 +11,17 @@ extern int tc_generation; -void tc_get (tc_area *area, int width, int height); -void tc_put (tc_area *area); -void tc_clear (); +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; @@ -24,6 +30,7 @@ struct tc_texture *next; GLuint name; int avail; + char *saved; /* stores saved texture data */ } tc_texture; typedef struct tc_slice { @@ -35,7 +42,7 @@ static tc_texture *first_texture; void -tc_clear () +tc_clear (void) { int i; @@ -54,6 +61,45 @@ } void +tex_backup (tc_texture *tex) +{ + tex->saved = 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 tc_get (tc_area *area, int width, int height) { int slice_height = MIN (height + TC_ROUND - 1, TC_HEIGHT) & ~(TC_ROUND - 1); @@ -77,15 +123,23 @@ if (!match) { match = g_slice_new (tc_texture); - match->next = first_texture; + match->next = first_texture; first_texture = match; - match->name = gen_texture (); - 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;