Search
lxdream.org :: lxdream/src/pvr2/texcache.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/texcache.c
changeset 1140:7dc1c71ece76
prev1135:68daed8f38af
next1142:fd82bfba61c4
author nkeynes
date Tue Oct 26 08:39:02 2010 +1000 (10 years ago)
permissions -rw-r--r--
last change Implement fragment shader to support palette textures 'directly', and
therefore avoid having to reload all palette textures whenever the palette
changes.
file annotate diff log raw
1.1 --- a/src/pvr2/texcache.c Sun Oct 24 11:50:17 2010 +1000
1.2 +++ b/src/pvr2/texcache.c Tue Oct 26 08:39:02 2010 +1000
1.3 @@ -22,6 +22,7 @@
1.4 #include <string.h>
1.5 #include "pvr2/pvr2.h"
1.6 #include "pvr2/pvr2mmio.h"
1.7 +#include "pvr2/glutil.h"
1.8
1.9 /** Specifies the maximum number of OpenGL
1.10 * textures we're willing to have open at a time. If more are
1.11 @@ -59,6 +60,9 @@
1.12 static struct texcache_entry texcache_active_list[MAX_TEXTURES];
1.13 static uint32_t texcache_palette_mode;
1.14 static uint32_t texcache_stride_width;
1.15 +static gboolean texcache_have_palette_shader;
1.16 +static gboolean texcache_palette_valid;
1.17 +static GLuint texcache_palette_texid;
1.18
1.19 /**
1.20 * Initialize the texture cache.
1.21 @@ -77,7 +81,7 @@
1.22 }
1.23 texcache_free_ptr = 0;
1.24 texcache_ref_counter = 0;
1.25 - texcache_palette_mode = 0;
1.26 + texcache_palette_mode = -1;
1.27 texcache_stride_width = 0;
1.28 }
1.29
1.30 @@ -90,6 +94,23 @@
1.31 int i;
1.32 GLuint texids[MAX_TEXTURES];
1.33
1.34 + if( glsl_is_supported() && isGLMultitextureSupported ) {
1.35 + texcache_have_palette_shader = TRUE;
1.36 + texcache_palette_valid = FALSE;
1.37 + glGenTextures(1, &texcache_palette_texid );
1.38 +
1.39 + /* Bind the texture and set the params */
1.40 + glActiveTexture(GL_TEXTURE1);
1.41 + glBindTexture(GL_TEXTURE_1D, texcache_palette_texid);
1.42 + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1.43 + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1.44 + glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP );
1.45 + glActiveTexture(GL_TEXTURE0);
1.46 +
1.47 + } else {
1.48 + texcache_have_palette_shader = FALSE;
1.49 + }
1.50 +
1.51 glGenTextures( MAX_TEXTURES, texids );
1.52 for( i=0; i<MAX_TEXTURES; i++ ) {
1.53 texcache_active_list[i].texture_id = texids[i];
1.54 @@ -137,6 +158,9 @@
1.55 int i;
1.56 texcache_flush();
1.57
1.58 + if( texcache_have_palette_shader )
1.59 + glDeleteTextures( 1, &texcache_palette_texid );
1.60 +
1.61 for( i=0; i<MAX_TEXTURES; i++ ) {
1.62 texids[i] = texcache_active_list[i].texture_id;
1.63 }
1.64 @@ -220,20 +244,83 @@
1.65 }
1.66
1.67 /**
1.68 - * Mark all textures that use the palette table as needing a re-read (ie
1.69 - * for when the palette is changed. We could track exactly which ones are
1.70 - * affected, but it's not clear that the extra maintanence overhead is
1.71 - * worthwhile.
1.72 + * Load the palette into 4 textures of 256 entries each. This mirrors the
1.73 + * banking done by the PVR2 for 8-bit textures, and also ensures that we
1.74 + * can use 8-bit paletted textures ourselves.
1.75 + */
1.76 +static void texcache_load_palette_texture( gboolean format_changed )
1.77 +{
1.78 + GLint format, type, intFormat = GL_RGBA;
1.79 + unsigned i;
1.80 + int bpp = 2;
1.81 + uint32_t *palette = (uint32_t *)mmio_region_PVR2PAL.mem;
1.82 + uint16_t packed_palette[1024];
1.83 + char *data = (char *)palette;
1.84 +
1.85 + switch( texcache_palette_mode ) {
1.86 + case 0: /* ARGB1555 */
1.87 + format = GL_BGRA;
1.88 + type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
1.89 + break;
1.90 + case 1: /* RGB565 */
1.91 + intFormat = GL_RGB;
1.92 + format = GL_RGB;
1.93 + type = GL_UNSIGNED_SHORT_5_6_5;
1.94 + break;
1.95 + case 2: /* ARGB4444 */
1.96 + format = GL_BGRA;
1.97 + type = GL_UNSIGNED_SHORT_4_4_4_4_REV;
1.98 + break;
1.99 + case 3: /* ARGB8888 */
1.100 + format = GL_BGRA;
1.101 + type = GL_UNSIGNED_BYTE;
1.102 + bpp = 4;
1.103 + break;
1.104 + default:
1.105 + break; /* Can't happen */
1.106 + }
1.107 +
1.108 +
1.109 + if( bpp == 2 ) {
1.110 + for( i=0; i<1024; i++ ) {
1.111 + packed_palette[i] = (uint16_t)palette[i];
1.112 + }
1.113 + data = (char *)packed_palette;
1.114 +
1.115 + }
1.116 +
1.117 + glActiveTexture(GL_TEXTURE1);
1.118 +// glBindTexture(GL_TEXTURE_1D, texcache_palette_texid);
1.119 + if( format_changed )
1.120 + glTexImage1D(GL_TEXTURE_1D, 0, intFormat, 1024, 0, format, type, data );
1.121 + else
1.122 + glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 1024, format, type, data);
1.123 +// glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1.124 +// glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1.125 +// glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP );
1.126 + glActiveTexture(GL_TEXTURE0);
1.127 + texcache_palette_valid = TRUE;
1.128 +}
1.129 +
1.130 +
1.131 +/**
1.132 + * Mark the palette as having changed. If we have palette support (via shaders)
1.133 + * we just flag the palette, otherwise we have to invalidate all palette
1.134 + * textures.
1.135 */
1.136 void texcache_invalidate_palette( )
1.137 {
1.138 - int i;
1.139 - for( i=0; i<MAX_TEXTURES; i++ ) {
1.140 - if( texcache_active_list[i].texture_addr != -1 &&
1.141 - PVR2_TEX_IS_PALETTE(texcache_active_list[i].tex_mode) ) {
1.142 - texcache_evict( i );
1.143 - texcache_free_ptr--;
1.144 - texcache_free_list[texcache_free_ptr] = i;
1.145 + if( texcache_have_palette_shader ) {
1.146 + texcache_palette_valid = FALSE;
1.147 + } else {
1.148 + int i;
1.149 + for( i=0; i<MAX_TEXTURES; i++ ) {
1.150 + if( texcache_active_list[i].texture_addr != -1 &&
1.151 + PVR2_TEX_IS_PALETTE(texcache_active_list[i].tex_mode) ) {
1.152 + texcache_evict( i );
1.153 + texcache_free_ptr--;
1.154 + texcache_free_list[texcache_free_ptr] = i;
1.155 + }
1.156 }
1.157 }
1.158 }
1.159 @@ -256,13 +343,19 @@
1.160
1.161 void texcache_begin_scene( uint32_t palette_mode, uint32_t stride )
1.162 {
1.163 - if( palette_mode != texcache_palette_mode )
1.164 + gboolean format_changed = FALSE;
1.165 + if( palette_mode != texcache_palette_mode ) {
1.166 texcache_invalidate_palette();
1.167 + format_changed = TRUE;
1.168 + }
1.169 if( stride != texcache_stride_width )
1.170 texcache_invalidate_stride();
1.171
1.172 texcache_palette_mode = palette_mode;
1.173 texcache_stride_width = stride;
1.174 +
1.175 + if( !texcache_palette_valid && texcache_have_palette_shader )
1.176 + texcache_load_palette_texture(format_changed);
1.177 }
1.178
1.179 static void decode_pal8_to_32( uint32_t *out, uint8_t *in, int inbytes, uint32_t *pal )
1.180 @@ -291,6 +384,17 @@
1.181 }
1.182 }
1.183
1.184 +static void decode_pal4_to_pal8( uint8_t *out, uint8_t *in, int inbytes )
1.185 +{
1.186 + int i;
1.187 + for( i=0; i<inbytes; i++ ) {
1.188 + *out++ = (uint8_t)(*in & 0x0F);
1.189 + *out++ = (uint8_t)(*in >> 4);
1.190 + in++;
1.191 + }
1.192 +}
1.193 +
1.194 +
1.195
1.196 static void decode_pal4_to_16( uint16_t *out, uint8_t *in, int inbytes, uint32_t *pal )
1.197 {
1.198 @@ -395,7 +499,9 @@
1.199 GLint intFormat = GL_RGBA, format, type;
1.200 int tex_format = mode & PVR2_TEX_FORMAT_MASK;
1.201 struct vq_codebook codebook;
1.202 - GLint filter = GL_LINEAR;
1.203 + GLint min_filter = GL_LINEAR;
1.204 + GLint max_filter = GL_LINEAR;
1.205 + GLint mipmapfilter = GL_LINEAR_MIPMAP_LINEAR;
1.206
1.207 glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
1.208
1.209 @@ -403,30 +509,39 @@
1.210 switch( tex_format ) {
1.211 case PVR2_TEX_FORMAT_IDX4:
1.212 case PVR2_TEX_FORMAT_IDX8:
1.213 - /* For indexed-colour modes, we need to lookup the palette control
1.214 - * word to determine the de-indexed texture format.
1.215 - */
1.216 - switch( texcache_palette_mode ) {
1.217 - case 0: /* ARGB1555 */
1.218 - format = GL_BGRA;
1.219 - type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
1.220 - break;
1.221 - case 1: /* RGB565 */
1.222 - intFormat = GL_RGB;
1.223 - format = GL_RGB;
1.224 - type = GL_UNSIGNED_SHORT_5_6_5;
1.225 - break;
1.226 - case 2: /* ARGB4444 */
1.227 - format = GL_BGRA;
1.228 - type = GL_UNSIGNED_SHORT_4_4_4_4_REV;
1.229 - break;
1.230 - case 3: /* ARGB8888 */
1.231 - format = GL_BGRA;
1.232 + if( texcache_have_palette_shader ) {
1.233 + intFormat = GL_ALPHA8;
1.234 + format = GL_ALPHA;
1.235 type = GL_UNSIGNED_BYTE;
1.236 - bpp_shift = 2;
1.237 - break;
1.238 - default:
1.239 - return; /* Can't happen, but it makes gcc stop complaining */
1.240 + bpp_shift = 0;
1.241 + min_filter = max_filter = GL_NEAREST;
1.242 + mipmapfilter = GL_NEAREST_MIPMAP_NEAREST;
1.243 + } else {
1.244 + /* For indexed-colour modes, we need to lookup the palette control
1.245 + * word to determine the de-indexed texture format.
1.246 + */
1.247 + switch( texcache_palette_mode ) {
1.248 + case 0: /* ARGB1555 */
1.249 + format = GL_BGRA;
1.250 + type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
1.251 + break;
1.252 + case 1: /* RGB565 */
1.253 + intFormat = GL_RGB;
1.254 + format = GL_RGB;
1.255 + type = GL_UNSIGNED_SHORT_5_6_5;
1.256 + break;
1.257 + case 2: /* ARGB4444 */
1.258 + format = GL_BGRA;
1.259 + type = GL_UNSIGNED_SHORT_4_4_4_4_REV;
1.260 + break;
1.261 + case 3: /* ARGB8888 */
1.262 + format = GL_BGRA;
1.263 + type = GL_UNSIGNED_BYTE;
1.264 + bpp_shift = 2;
1.265 + break;
1.266 + default:
1.267 + return; /* Can't happen, but it makes gcc stop complaining */
1.268 + }
1.269 }
1.270 break;
1.271
1.272 @@ -469,8 +584,8 @@
1.273 pvr2_vram64_read_stride( data, width<<bpp_shift, texture_addr, texcache_stride_width<<bpp_shift, height );
1.274 }
1.275 glTexImage2D( GL_TEXTURE_2D, 0, intFormat, width, height, 0, format, type, data );
1.276 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
1.277 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1.278 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter);
1.279 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, max_filter);
1.280 return;
1.281 }
1.282
1.283 @@ -484,7 +599,7 @@
1.284 int level=0, last_level = 0, mip_width = width, mip_height = height, src_bytes, dest_bytes;
1.285 if( PVR2_TEX_IS_MIPMAPPED(mode) ) {
1.286 uint32_t src_offset = 0;
1.287 - filter = GL_LINEAR_MIPMAP_LINEAR;
1.288 + min_filter = mipmapfilter;
1.289 mip_height = height = width;
1.290 while( (1<<last_level) < width ) {
1.291 last_level++;
1.292 @@ -513,26 +628,35 @@
1.293 unsigned char data[dest_bytes];
1.294 /* load data from image, detwiddling/uncompressing as required */
1.295 if( tex_format == PVR2_TEX_FORMAT_IDX8 ) {
1.296 - src_bytes = (mip_width * mip_height);
1.297 - int bank = (mode >> 25) &0x03;
1.298 - uint32_t *palette = ((uint32_t *)mmio_region_PVR2PAL.mem) + (bank<<8);
1.299 - unsigned char tmp[src_bytes];
1.300 - pvr2_vram64_read_twiddled_8( tmp, texture_addr, mip_width, mip_height );
1.301 - if( bpp_shift == 2 ) {
1.302 - decode_pal8_to_32( (uint32_t *)data, tmp, src_bytes, palette );
1.303 + if( texcache_have_palette_shader ) {
1.304 + pvr2_vram64_read_twiddled_8( data, texture_addr, mip_width, mip_height );
1.305 } else {
1.306 - decode_pal8_to_16( (uint16_t *)data, tmp, src_bytes, palette );
1.307 + src_bytes = (mip_width * mip_height);
1.308 + int bank = (mode >> 25) &0x03;
1.309 + uint32_t *palette = ((uint32_t *)mmio_region_PVR2PAL.mem) + (bank<<8);
1.310 + unsigned char tmp[src_bytes];
1.311 + pvr2_vram64_read_twiddled_8( tmp, texture_addr, mip_width, mip_height );
1.312 + if( bpp_shift == 2 ) {
1.313 + decode_pal8_to_32( (uint32_t *)data, tmp, src_bytes, palette );
1.314 + } else {
1.315 + decode_pal8_to_16( (uint16_t *)data, tmp, src_bytes, palette );
1.316 + }
1.317 }
1.318 } else if( tex_format == PVR2_TEX_FORMAT_IDX4 ) {
1.319 src_bytes = (mip_width * mip_height) >> 1;
1.320 - int bank = (mode >>21 ) & 0x3F;
1.321 - uint32_t *palette = ((uint32_t *)mmio_region_PVR2PAL.mem) + (bank<<4);
1.322 unsigned char tmp[src_bytes];
1.323 - pvr2_vram64_read_twiddled_4( tmp, texture_addr, mip_width, mip_height );
1.324 - if( bpp_shift == 2 ) {
1.325 - decode_pal4_to_32( (uint32_t *)data, tmp, src_bytes, palette );
1.326 + if( texcache_have_palette_shader ) {
1.327 + pvr2_vram64_read_twiddled_4( tmp, texture_addr, mip_width, mip_height );
1.328 + decode_pal4_to_pal8( data, tmp, src_bytes );
1.329 } else {
1.330 - decode_pal4_to_16( (uint16_t *)data, tmp, src_bytes, palette );
1.331 + int bank = (mode >>21 ) & 0x3F;
1.332 + uint32_t *palette = ((uint32_t *)mmio_region_PVR2PAL.mem) + (bank<<4);
1.333 + pvr2_vram64_read_twiddled_4( tmp, texture_addr, mip_width, mip_height );
1.334 + if( bpp_shift == 2 ) {
1.335 + decode_pal4_to_32( (uint32_t *)data, tmp, src_bytes, palette );
1.336 + } else {
1.337 + decode_pal4_to_16( (uint16_t *)data, tmp, src_bytes, palette );
1.338 + }
1.339 }
1.340 } else if( tex_format == PVR2_TEX_FORMAT_YUV422 ) {
1.341 src_bytes = ((mip_width*mip_height)<<1);
1.342 @@ -575,8 +699,8 @@
1.343 }
1.344 }
1.345
1.346 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
1.347 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1.348 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter);
1.349 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, max_filter);
1.350 }
1.351
1.352 static int texcache_find_texture_slot( uint32_t poly2_masked_word, uint32_t texture_word )
1.353 @@ -646,11 +770,15 @@
1.354 GLuint texcache_get_texture( uint32_t poly2_word, uint32_t texture_word )
1.355 {
1.356 poly2_word &= 0x000F803F; /* Get just the texture-relevant bits */
1.357 - int slot = texcache_find_texture_slot( poly2_word, texture_word );
1.358 + uint32_t texture_lookup = texture_word;
1.359 + if( PVR2_TEX_IS_PALETTE(texture_lookup) ) {
1.360 + texture_lookup &= 0xF81FFFFF; /* Mask out the bank bits */
1.361 + }
1.362 + int slot = texcache_find_texture_slot( poly2_word, texture_lookup );
1.363
1.364 if( slot == -1 ) {
1.365 /* Not found - check the free list */
1.366 - slot = texcache_alloc_texture_slot( poly2_word, texture_word );
1.367 + slot = texcache_alloc_texture_slot( poly2_word, texture_lookup );
1.368
1.369 /* Construct the GL texture */
1.370 uint32_t texture_addr = (texture_word & 0x000FFFFF)<<3;
1.371 @@ -750,3 +878,23 @@
1.372 assert( slot_found[i] != 0 );
1.373 }
1.374 }
1.375 +
1.376 +/**
1.377 + * Dump the contents of the texture cache
1.378 + */
1.379 +void texcache_dump()
1.380 +{
1.381 + unsigned i;
1.382 + for( i=0; i< PVR2_RAM_PAGES; i++ ) {
1.383 + int slot = texcache_page_lookup[i];
1.384 + while( slot != EMPTY_ENTRY ) {
1.385 + fprintf( stderr, "%-3d: %08X %dx%d (%08X %08X)\n", slot,
1.386 + texcache_active_list[slot].texture_addr,
1.387 + POLY2_TEX_WIDTH(texcache_active_list[slot].poly2_mode),
1.388 + POLY2_TEX_HEIGHT(texcache_active_list[slot].poly2_mode),
1.389 + texcache_active_list[slot].poly2_mode,
1.390 + texcache_active_list[slot].tex_mode );
1.391 + slot = texcache_active_list[slot].next;
1.392 + }
1.393 + }
1.394 +}
.