filename | src/pvr2/texcache.c |
changeset | 270:1e151174ef51 |
prev | 224:289ddaeeebb3 |
next | 282:01e53698ff38 |
author | nkeynes |
date | Thu Jan 11 06:51:11 2007 +0000 (16 years ago) |
permissions | -rw-r--r-- |
last change | Fix crash in texcache_evict Fix crash decoding small VQ textures Implement mip-mapped textures of all types |
file | annotate | diff | log | raw |
1.1 --- a/src/pvr2/texcache.c Tue Sep 12 13:33:18 2006 +00001.2 +++ b/src/pvr2/texcache.c Thu Jan 11 06:51:11 2007 +00001.3 @@ -1,5 +1,5 @@1.4 /**1.5 - * $Id: texcache.c,v 1.8 2006-09-12 13:33:18 nkeynes Exp $1.6 + * $Id: texcache.c,v 1.9 2007-01-11 06:51:11 nkeynes Exp $1.7 *1.8 * Texture cache. Responsible for maintaining a working set of OpenGL1.9 * textures.1.10 @@ -159,7 +159,7 @@1.11 }1.13 /* Remove the selected slot from the lookup table */1.14 - uint32_t evict_page = texcache_active_list[slot].texture_addr;1.15 + uint32_t evict_page = texcache_active_list[slot].texture_addr >> 12;1.16 texcache_entry_index replace_next = texcache_active_list[slot].next;1.17 texcache_active_list[slot].next = EMPTY_ENTRY; /* Just for safety */1.18 if( texcache_page_lookup[evict_page] == slot ) {1.19 @@ -245,31 +245,36 @@1.20 }1.21 }1.23 +static void vq_get_codebook( struct vq_codebook *codebook,1.24 + uint16_t *input )1.25 +{1.26 + /* Detwiddle the codebook, for the sake of my own sanity if nothing else */1.27 + uint16_t *p = (uint16_t *)input;1.28 + int i;1.29 + for( i=0; i<256; i++ ) {1.30 + codebook->quad[i][0] = *p++;1.31 + codebook->quad[i][2] = *p++;1.32 + codebook->quad[i][1] = *p++;1.33 + codebook->quad[i][3] = *p++;1.34 + }1.35 +}1.36 +1.37 +1.38 static void vq_decode( int width, int height, char *input, uint16_t *output,1.39 - int twiddled ) {1.40 - struct vq_codebook codebook;1.41 + struct vq_codebook *codebook, int twiddled ) {1.42 int i,j;1.44 - /* Detwiddle the codebook, for the sake of my own sanity if nothing else */1.45 - uint16_t *p = (uint16_t *)input;1.46 - for( i=0; i<256; i++ ) {1.47 - codebook.quad[i][0] = *p++;1.48 - codebook.quad[i][2] = *p++;1.49 - codebook.quad[i][1] = *p++;1.50 - codebook.quad[i][3] = *p++;1.51 - }1.52 -1.53 - uint8_t *c = (uint8_t *)p;1.54 + uint8_t *c = (uint8_t *)input;1.55 if( twiddled ) {1.56 - detwiddle_vq_to_16( 0, 0, width, width, &c, output, &codebook );1.57 + detwiddle_vq_to_16( 0, 0, width, width, &c, output, codebook );1.58 } else {1.59 for( j=0; j<height; j+=2 ) {1.60 for( i=0; i<width; i+=2 ) {1.61 uint8_t code = *c;1.62 - output[i + j*width] = codebook.quad[code][0];1.63 - output[i + 1 + j*width] = codebook.quad[code][1];1.64 - output[i + (j+1)*width] = codebook.quad[code][2];1.65 - output[i + 1 + (j+1)*width] = codebook.quad[code][3];1.66 + output[i + j*width] = codebook->quad[code][0];1.67 + output[i + 1 + j*width] = codebook->quad[code][1];1.68 + output[i + (j+1)*width] = codebook->quad[code][2];1.69 + output[i + 1 + (j+1)*width] = codebook->quad[code][3];1.70 }1.71 }1.72 }1.73 @@ -285,9 +290,14 @@1.74 int shift = 1;1.75 GLint intFormat, format, type;1.76 int tex_format = mode & PVR2_TEX_FORMAT_MASK;1.77 + struct vq_codebook codebook;1.78 + GLint filter = GL_LINEAR;1.80 - if( tex_format == PVR2_TEX_FORMAT_IDX8 ||1.81 - tex_format == PVR2_TEX_FORMAT_IDX4 ) {1.82 + /* Decode the format parameters */1.83 + switch( tex_format ) {1.84 + case PVR2_TEX_FORMAT_IDX4:1.85 + ERROR( "4-bit indexed textures not supported" );1.86 + case PVR2_TEX_FORMAT_IDX8:1.87 switch( MMIO_READ( PVR2, RENDER_PALETTE ) & 0x03 ) {1.88 case 0: /* ARGB1555 */1.89 intFormat = GL_RGB5_A1;1.90 @@ -311,94 +321,103 @@1.91 shift = 2;1.92 break;1.93 }1.94 + bytes <<= shift;1.95 + break;1.96 +1.97 + case PVR2_TEX_FORMAT_ARGB1555:1.98 + bytes <<= 1;1.99 + intFormat = GL_RGB5_A1;1.100 + format = GL_RGBA;1.101 + type = GL_UNSIGNED_SHORT_1_5_5_5_REV;1.102 + break;1.103 + case PVR2_TEX_FORMAT_RGB565:1.104 + bytes <<= 1;1.105 + intFormat = GL_RGB;1.106 + format = GL_RGB;1.107 + type = GL_UNSIGNED_SHORT_5_6_5_REV;1.108 + break;1.109 + case PVR2_TEX_FORMAT_ARGB4444:1.110 + bytes <<= 1;1.111 + intFormat = GL_RGBA4;1.112 + format = GL_BGRA;1.113 + type = GL_UNSIGNED_SHORT_4_4_4_4_REV;1.114 + break;1.115 + case PVR2_TEX_FORMAT_YUV422:1.116 + ERROR( "YUV textures not supported" );1.117 + break;1.118 + case PVR2_TEX_FORMAT_BUMPMAP:1.119 + ERROR( "Bumpmap not supported" );1.120 + break;1.121 + }1.122 +1.123 + int level=0, last_level = 0, mip_width = width, mip_height = height, mip_bytes = bytes;1.124 + if( PVR2_TEX_IS_MIPMAPPED(mode) ) {1.125 + int i;1.126 + for( i=0; 1<<(i+1) < width; i++ );1.127 + last_level = i;1.128 + mip_width = width >> i;1.129 + mip_height= height >> i;1.130 + mip_bytes = bytes >> (i*2);1.131 + filter = GL_LINEAR_MIPMAP_LINEAR;1.132 + }1.134 + if( PVR2_TEX_IS_COMPRESSED(mode) ) {1.135 + uint16_t tmp[VQ_CODEBOOK_SIZE];1.136 + pvr2_vram64_read( (char *)tmp, texture_addr, VQ_CODEBOOK_SIZE );1.137 + texture_addr += VQ_CODEBOOK_SIZE;1.138 + vq_get_codebook( &codebook, tmp );1.139 + }1.140 +1.141 + for( level=last_level; level>= 0; level-- ) {1.142 + char data[mip_bytes];1.143 + /* load data from image, detwiddling/uncompressing as required */1.144 if( tex_format == PVR2_TEX_FORMAT_IDX8 ) {1.145 - unsigned char data[bytes<<shift];1.146 + int inputlength = mip_bytes >> shift;1.147 int bank = (mode >> 25) &0x03;1.148 char *palette = mmio_region_PVR2PAL.mem + (bank * (256 << shift));1.149 - int i;1.150 + char tmp[inputlength];1.151 + char *p = tmp;1.152 + pvr2_vram64_read( tmp, texture_addr, inputlength );1.153 if( shift == 2 ) {1.154 - char tmp[bytes];1.155 - char *p = tmp;1.156 - pvr2_vram64_read( tmp, texture_addr, bytes );1.157 - detwiddle_pal8_to_32( 0, 0, width, width, &p,1.158 + detwiddle_pal8_to_32( 0, 0, mip_width, mip_width, &p,1.159 (uint32_t *)data, (uint32_t *)palette );1.160 } else {1.161 - char tmp[bytes];1.162 - char *p = tmp;1.163 - pvr2_vram64_read( tmp, texture_addr, bytes );1.164 - detwiddle_pal8_to_16( 0, 0, width, width, &p,1.165 + detwiddle_pal8_to_16( 0, 0, mip_width, mip_width, &p,1.166 (uint16_t *)data, (uint16_t *)palette );1.167 }1.168 - glTexImage2D( GL_TEXTURE_2D, 0, intFormat, width, height, 0, format, type,1.169 - data );1.170 -1.171 + } else if( PVR2_TEX_IS_COMPRESSED(mode) ) {1.172 + int inputlength = ((mip_width*mip_height) >> 2);1.173 + char tmp[inputlength];1.174 + pvr2_vram64_read( tmp, texture_addr, inputlength );1.175 + vq_decode( mip_width, mip_height, tmp, (uint16_t *)&data, &codebook,1.176 + PVR2_TEX_IS_TWIDDLED(mode) );1.177 + } else if( PVR2_TEX_IS_TWIDDLED(mode) ) {1.178 + char tmp[mip_bytes];1.179 + uint16_t *p = (uint16_t *)tmp;1.180 + pvr2_vram64_read( tmp, texture_addr, mip_bytes );1.181 + /* Untwiddle */1.182 + detwiddle_16_to_16( 0, 0, mip_width, mip_width, &p, (uint16_t *)&data );1.183 + } else {1.184 + pvr2_vram64_read( data, texture_addr, mip_bytes );1.185 }1.186 - } else {1.187 - switch( tex_format ) {1.188 - case PVR2_TEX_FORMAT_ARGB1555:1.189 - bytes <<= 1;1.190 - intFormat = GL_RGB5_A1;1.191 - format = GL_RGBA;1.192 - type = GL_UNSIGNED_SHORT_1_5_5_5_REV;1.193 - break;1.194 - case PVR2_TEX_FORMAT_RGB565:1.195 - bytes <<= 1;1.196 - intFormat = GL_RGB;1.197 - format = GL_RGB;1.198 - type = GL_UNSIGNED_SHORT_5_6_5_REV;1.199 - break;1.200 - case PVR2_TEX_FORMAT_ARGB4444:1.201 - bytes <<= 1;1.202 - intFormat = GL_RGBA4;1.203 - format = GL_BGRA;1.204 - type = GL_UNSIGNED_SHORT_4_4_4_4_REV;1.205 - break;1.206 - case PVR2_TEX_FORMAT_YUV422:1.207 - ERROR( "YUV textures not supported" );1.208 - break;1.209 - case PVR2_TEX_FORMAT_BUMPMAP:1.210 - ERROR( "Bumpmap not supported" );1.211 - break;1.212 - case PVR2_TEX_FORMAT_IDX4:1.213 - /* Supported? */1.214 - bytes >>= 1;1.215 - intFormat = GL_INTENSITY4;1.216 - format = GL_COLOR_INDEX;1.217 - type = GL_UNSIGNED_BYTE;1.218 - shift = 0;1.219 - break;1.220 - case PVR2_TEX_FORMAT_IDX8:1.221 - intFormat = GL_INTENSITY8;1.222 - format = GL_COLOR_INDEX;1.223 - type = GL_UNSIGNED_BYTE;1.224 - shift = 0;1.225 - break;1.226 - }1.227 -1.228 - char data[bytes];1.229 - /* load data from image, detwiddling/uncompressing as required */1.230 - if( PVR2_TEX_IS_COMPRESSED(mode) ) {1.231 - int inputlength = VQ_CODEBOOK_SIZE +1.232 - ((width*height) >> 2); /* + mip maps */1.233 - char tmp[bytes];1.234 - pvr2_vram64_read( tmp, texture_addr, inputlength );1.235 - vq_decode( width, height, tmp, (uint16_t *)&data, PVR2_TEX_IS_TWIDDLED(mode) );1.236 - } else if( PVR2_TEX_IS_TWIDDLED(mode) ) {1.237 - char tmp[bytes];1.238 - uint16_t *p = (uint16_t *)tmp;1.239 - pvr2_vram64_read( tmp, texture_addr, bytes );1.240 - /* Untwiddle */1.241 - detwiddle_16_to_16( 0, 0, width, width, &p, (uint16_t *)&data );1.242 - } else {1.243 - pvr2_vram64_read( data, texture_addr, bytes );1.244 +1.245 + if( PVR2_TEX_IS_MIPMAPPED(mode) && mip_width == 2 ) {1.246 + /* Opengl requires a 1x1 texture, but the PVR2 doesn't. This should1.247 + * strictly speaking be the average of the 2x2 texture, but we're1.248 + * lazy at the moment */1.249 + glTexImage2D( GL_TEXTURE_2D, level+1, intFormat, 1, 1, 0, format, type, data );1.250 }1.252 /* Pass to GL */1.253 - glTexImage2D( GL_TEXTURE_2D, 0, intFormat, width, height, 0, format, type,1.254 + glTexImage2D( GL_TEXTURE_2D, level, intFormat, mip_width, mip_height, 0, format, type,1.255 data );1.256 + texture_addr += mip_bytes;1.257 + mip_width <<= 1;1.258 + mip_height <<= 1;1.259 + mip_bytes <<= 2;1.260 }1.261 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);1.262 +1.263 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);1.264 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);1.265 }
.