Search
lxdream.org :: lxdream :: r270:1e151174ef51
lxdream 0.9.1
released Jun 29
Download Now
changeset270:1e151174ef51
parent269:e41f9b1490d1
child271:2ec052d24881
authornkeynes
dateThu Jan 11 06:51:11 2007 +0000 (17 years ago)
Fix crash in texcache_evict
Fix crash decoding small VQ textures
Implement mip-mapped textures of all types
src/pvr2/texcache.c
1.1 --- a/src/pvr2/texcache.c Thu Jan 11 06:50:11 2007 +0000
1.2 +++ b/src/pvr2/texcache.c Thu Jan 11 06:51:11 2007 +0000
1.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 OpenGL
1.9 * textures.
1.10 @@ -159,7 +159,7 @@
1.11 }
1.12
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.22
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.43
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.79
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.133
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 should
1.247 + * strictly speaking be the average of the 2x2 texture, but we're
1.248 + * lazy at the moment */
1.249 + glTexImage2D( GL_TEXTURE_2D, level+1, intFormat, 1, 1, 0, format, type, data );
1.250 }
1.251
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 }
1.266
.