filename | src/pvr2/pvr2mem.c |
changeset | 315:2d8ba198d62c |
prev | 310:00cd8897ad5e |
next | 325:5717ae5d4746 |
author | nkeynes |
date | Tue Jan 23 11:19:32 2007 +0000 (17 years ago) |
permissions | -rw-r--r-- |
last change | Refactor render buffer read/write to pvr2mem.c Implement 4-bit indexed textures (tentatively) Fix RGB24 support |
file | annotate | diff | log | raw |
1.1 --- a/src/pvr2/pvr2mem.c Mon Jan 22 11:45:37 2007 +00001.2 +++ b/src/pvr2/pvr2mem.c Tue Jan 23 11:19:32 2007 +00001.3 @@ -1,5 +1,5 @@1.4 /**1.5 - * $Id: pvr2mem.c,v 1.4 2007-01-22 11:45:37 nkeynes Exp $1.6 + * $Id: pvr2mem.c,v 1.5 2007-01-23 11:19:32 nkeynes Exp $1.7 *1.8 * PVR2 (Video) VRAM handling routines (mainly for the 64-bit region)1.9 *1.10 @@ -165,6 +165,7 @@1.11 }1.12 }1.14 +1.15 /**1.16 * @param dest Destination image buffer1.17 * @param banks Source data expressed as two bank pointers1.18 @@ -172,26 +173,60 @@1.19 * to read is (0..3)1.20 * @param x1,y1 Destination coordinates1.21 * @param width Width of current destination block1.22 - * @param image_width Total width of image (ie stride)1.23 + * @param stride Total width of image (ie stride) in bytes1.24 + */1.25 +1.26 +static void pvr2_vram64_detwiddle_4( uint8_t *dest, uint8_t *banks[2], int offset,1.27 + int x1, int y1, int width, int stride )1.28 +{1.29 + if( width == 2 ) {1.30 + x1 = x1 >> 1;1.31 + uint8_t t1 = *banks[offset<4?0:1]++;1.32 + uint8_t t2 = *banks[offset<3?0:1]++;1.33 + dest[y1*stride + x1] = (t1 & 0x0F) | (t2<<4);1.34 + dest[(y1+1)*stride + x1] = (t1>>4) | (t2&0xF0);1.35 + } else if( width == 4 ) {1.36 + pvr2_vram64_detwiddle_4( dest, banks, offset, x1, y1, 2, stride );1.37 + pvr2_vram64_detwiddle_4( dest, banks, offset+2, x1, y1+2, 2, stride );1.38 + pvr2_vram64_detwiddle_4( dest, banks, offset+4, x1+2, y1, 2, stride );1.39 + pvr2_vram64_detwiddle_4( dest, banks, offset+6, x1+2, y1+2, 2, stride );1.40 +1.41 + } else {1.42 + int subdivide = width >> 1;1.43 + pvr2_vram64_detwiddle_4( dest, banks, offset, x1, y1, subdivide, stride );1.44 + pvr2_vram64_detwiddle_4( dest, banks, offset, x1, y1+subdivide, subdivide, stride );1.45 + pvr2_vram64_detwiddle_4( dest, banks, offset, x1+subdivide, y1, subdivide, stride );1.46 + pvr2_vram64_detwiddle_4( dest, banks, offset, x1+subdivide, y1+subdivide, subdivide, stride );1.47 + }1.48 +}1.49 +1.50 +/**1.51 + * @param dest Destination image buffer1.52 + * @param banks Source data expressed as two bank pointers1.53 + * @param offset Offset into banks[0] specifying where the next byte1.54 + * to read is (0..3)1.55 + * @param x1,y1 Destination coordinates1.56 + * @param width Width of current destination block1.57 + * @param stride Total width of image (ie stride)1.58 */1.60 static void pvr2_vram64_detwiddle_8( uint8_t *dest, uint8_t *banks[2], int offset,1.61 - int x1, int y1, int width, int image_width )1.62 + int x1, int y1, int width, int stride )1.63 {1.64 if( width == 2 ) {1.65 - dest[y1*image_width + x1] = *banks[0]++;1.66 - dest[(y1+1)*image_width + x1] = *banks[offset<3?0:1]++;1.67 - dest[y1*image_width + x1 + 1] = *banks[offset<2?0:1]++;1.68 - dest[(y1+1)*image_width + x1 + 1] = *banks[offset==0?0:1]++;1.69 + dest[y1*stride + x1] = *banks[0]++;1.70 + dest[(y1+1)*stride + x1] = *banks[offset<3?0:1]++;1.71 + dest[y1*stride + x1 + 1] = *banks[offset<2?0:1]++;1.72 + dest[(y1+1)*stride + x1 + 1] = *banks[offset==0?0:1]++;1.73 uint8_t *tmp = banks[0]; /* swap banks */1.74 banks[0] = banks[1];1.75 banks[1] = tmp;1.76 } else {1.77 int subdivide = width >> 1;1.78 - pvr2_vram64_detwiddle_8( dest, banks, offset, x1, y1, subdivide, image_width );1.79 - pvr2_vram64_detwiddle_8( dest, banks, offset, x1, y1+subdivide, subdivide, image_width );1.80 - pvr2_vram64_detwiddle_8( dest, banks, offset, x1+subdivide, y1, subdivide, image_width );1.81 - pvr2_vram64_detwiddle_8( dest, banks, offset, x1+subdivide, y1+subdivide, subdivide, image_width );1.82 + pvr2_vram64_detwiddle_8( dest, banks, offset, x1, y1, subdivide, stride );1.83 + pvr2_vram64_detwiddle_8( dest, banks, offset, x1, y1+subdivide, subdivide, stride );1.84 + pvr2_vram64_detwiddle_8( dest, banks, offset, x1+subdivide, y1, subdivide, stride );1.85 + pvr2_vram64_detwiddle_8( dest, banks, offset, x1+subdivide, y1+subdivide, subdivide, stride );1.86 }1.87 }1.89 @@ -202,27 +237,70 @@1.90 * to read is (0 or 1)1.91 * @param x1,y1 Destination coordinates1.92 * @param width Width of current destination block1.93 - * @param image_width Total width of image (ie stride)1.94 + * @param stride Total width of image (ie stride)1.95 */1.97 static void pvr2_vram64_detwiddle_16( uint16_t *dest, uint16_t *banks[2], int offset,1.98 - int x1, int y1, int width, int image_width )1.99 + int x1, int y1, int width, int stride )1.100 {1.101 if( width == 2 ) {1.102 - dest[y1*image_width + x1] = *banks[0]++;1.103 - dest[(y1+1)*image_width + x1] = *banks[offset]++;1.104 - dest[y1*image_width + x1 + 1] = *banks[1]++;1.105 - dest[(y1+1)*image_width + x1 + 1] = *banks[offset^1]++;1.106 + dest[y1*stride + x1] = *banks[0]++;1.107 + dest[(y1+1)*stride + x1] = *banks[offset]++;1.108 + dest[y1*stride + x1 + 1] = *banks[1]++;1.109 + dest[(y1+1)*stride + x1 + 1] = *banks[offset^1]++;1.110 } else {1.111 int subdivide = width >> 1;1.112 - pvr2_vram64_detwiddle_16( dest, banks, offset, x1, y1, subdivide, image_width );1.113 - pvr2_vram64_detwiddle_16( dest, banks, offset, x1, y1+subdivide, subdivide, image_width );1.114 - pvr2_vram64_detwiddle_16( dest, banks, offset, x1+subdivide, y1, subdivide, image_width );1.115 - pvr2_vram64_detwiddle_16( dest, banks, offset, x1+subdivide, y1+subdivide, subdivide, image_width );1.116 + pvr2_vram64_detwiddle_16( dest, banks, offset, x1, y1, subdivide, stride );1.117 + pvr2_vram64_detwiddle_16( dest, banks, offset, x1, y1+subdivide, subdivide, stride );1.118 + pvr2_vram64_detwiddle_16( dest, banks, offset, x1+subdivide, y1, subdivide, stride );1.119 + pvr2_vram64_detwiddle_16( dest, banks, offset, x1+subdivide, y1+subdivide, subdivide, stride );1.120 }1.121 }1.123 /**1.124 + * Read an image from 64-bit vram stored as twiddled 4-bit pixels. The1.125 + * image is written out to the destination in detwiddled form.1.126 + * @param dest destination buffer, which must be at least width*height/2 in length1.127 + * @param srcaddr source address in vram1.128 + * @param width image width (must be a power of 2)1.129 + * @param height image height (must be a power of 2)1.130 + */1.131 +void pvr2_vram64_read_twiddled_4( char *dest, sh4addr_t srcaddr, uint32_t width, uint32_t height )1.132 +{1.133 + int offset_flag = (srcaddr & 0x07);1.134 + uint8_t *banks[2];1.135 + uint8_t *wdest = (uint8_t*)dest;1.136 + uint32_t stride = width >> 1;1.137 + int i,j;1.138 +1.139 + srcaddr = srcaddr & 0x7FFFF8;1.140 +1.141 + banks[0] = (uint8_t *)(video_base + (srcaddr>>1));1.142 + banks[1] = banks[0] + 0x400000;1.143 + if( offset_flag & 0x04 ) { // If source is not 64-bit aligned, swap the banks1.144 + uint8_t *tmp = banks[0];1.145 + banks[0] = banks[1];1.146 + banks[1] = tmp + 4;1.147 + offset_flag &= 0x03;1.148 + }1.149 + banks[0] += offset_flag;1.150 +1.151 + if( width > height ) {1.152 + for( i=0; i<width; i+=height ) {1.153 + pvr2_vram64_detwiddle_4( wdest, banks, offset_flag, i, 0, height, stride );1.154 + }1.155 + } else if( height > width ) {1.156 + for( i=0; i<height; i+=width ) {1.157 + pvr2_vram64_detwiddle_4( wdest, banks, offset_flag, 0, i, width, stride );1.158 + }1.159 + } else if( width == 1 ) {1.160 + *wdest = *banks[0];1.161 + } else {1.162 + pvr2_vram64_detwiddle_4( wdest, banks, offset_flag, 0, 0, width, stride );1.163 + }1.164 +}1.165 +1.166 +/**1.167 * Read an image from 64-bit vram stored as twiddled 8-bit pixels. The1.168 * image is written out to the destination in detwiddled form.1.169 * @param dest destination buffer, which must be at least width*height in length1.170 @@ -389,3 +467,131 @@1.171 pvr2_vram64_read( tmp, addr, length );1.172 fwrite_dump( tmp, length, f );1.173 }1.174 +1.175 +1.176 +1.177 +/**1.178 + * Flush the indicated render buffer back to PVR. Caller is responsible for1.179 + * tracking whether there is actually anything in the buffer.1.180 + *1.181 + * @param buffer A render buffer indicating the address to store to, and the1.182 + * format the data needs to be in.1.183 + * @param backBuffer TRUE to flush the back buffer, FALSE for1.184 + * the front buffer.1.185 + */1.186 +void pvr2_render_buffer_copy_to_sh4( pvr2_render_buffer_t buffer,1.187 + gboolean backBuffer )1.188 +{1.189 + if( buffer->render_addr == -1 )1.190 + return;1.191 + GLenum type, format = GL_BGRA;1.192 + int line_size = buffer->width, size;1.193 +1.194 + switch( buffer->colour_format ) {1.195 + case COLFMT_RGB565:1.196 + type = GL_UNSIGNED_SHORT_5_6_5;1.197 + format = GL_BGR;1.198 + line_size <<= 1;1.199 + break;1.200 + case COLFMT_RGB888:1.201 + type = GL_UNSIGNED_BYTE;1.202 + format = GL_BGR;1.203 + line_size = (line_size<<1)+line_size;1.204 + break;1.205 + case COLFMT_ARGB1555:1.206 + type = GL_UNSIGNED_SHORT_5_5_5_1;1.207 + line_size <<= 1;1.208 + break;1.209 + case COLFMT_ARGB4444:1.210 + type = GL_UNSIGNED_SHORT_4_4_4_4;1.211 + line_size <<= 1;1.212 + break;1.213 + case COLFMT_ARGB8888:1.214 + type = GL_UNSIGNED_INT_8_8_8_8;1.215 + line_size <<= 2;1.216 + break;1.217 + }1.218 + size = line_size * buffer->height;1.219 +1.220 + if( backBuffer ) {1.221 + glFinish();1.222 + glReadBuffer( GL_BACK );1.223 + } else {1.224 + glReadBuffer( GL_FRONT );1.225 + }1.226 +1.227 + if( buffer->render_addr & 0xFF000000 == 0x04000000 ) {1.228 + /* Interlaced buffer. Go the double copy... :( */1.229 + char target[size];1.230 + glReadPixels( 0, 0, buffer->width, buffer->height, format, type, target );1.231 + pvr2_vram64_write( buffer->render_addr, target, size );1.232 + } else {1.233 + /* Regular buffer */1.234 + char target[size];1.235 + glReadPixels( 0, 0, buffer->width, buffer->height, format, type, target );1.236 + pvr2_vram_write_invert( buffer->render_addr, target, size, line_size );1.237 + }1.238 +}1.239 +1.240 +1.241 +/**1.242 + * Copy data from PVR ram into the GL render buffer.1.243 + *1.244 + * @param buffer A render buffer indicating the address to read from, and the1.245 + * format the data is in.1.246 + * @param backBuffer TRUE to write the back buffer, FALSE for1.247 + * the front buffer.1.248 + */1.249 +void pvr2_render_buffer_copy_from_sh4( pvr2_render_buffer_t buffer,1.250 + gboolean backBuffer )1.251 +{1.252 + if( buffer->render_addr == -1 )1.253 + return;1.254 + GLenum type, format = GL_RGBA;1.255 + int size = buffer->width * buffer->height;1.256 +1.257 + switch( buffer->colour_format ) {1.258 + case COLFMT_RGB565:1.259 + type = GL_UNSIGNED_SHORT_5_6_5;1.260 + format = GL_RGB;1.261 + size <<= 1;1.262 + break;1.263 + case COLFMT_RGB888:1.264 + type = GL_UNSIGNED_BYTE;1.265 + format = GL_BGR;1.266 + size = (size<<1)+size;1.267 + break;1.268 + case COLFMT_ARGB1555:1.269 + type = GL_UNSIGNED_SHORT_5_5_5_1;1.270 + size <<= 1;1.271 + break;1.272 + case COLFMT_ARGB4444:1.273 + type = GL_UNSIGNED_SHORT_4_4_4_4;1.274 + size <<= 1;1.275 + break;1.276 + case COLFMT_ARGB8888:1.277 + type = GL_UNSIGNED_INT_8_8_8_8;1.278 + size <<= 2;1.279 + break;1.280 + }1.281 +1.282 + if( backBuffer ) {1.283 + glDrawBuffer( GL_BACK );1.284 + } else {1.285 + glDrawBuffer( GL_FRONT );1.286 + }1.287 +1.288 + glRasterPos2i( 0, 0 );1.289 + if( buffer->render_addr & 0xFF000000 == 0x04000000 ) {1.290 + /* Interlaced buffer. Go the double copy... :( */1.291 + char target[size];1.292 + pvr2_vram64_read( target, buffer->render_addr, size );1.293 + glDrawPixels( buffer->width, buffer->height,1.294 + format, type, target );1.295 + } else {1.296 + /* Regular buffer - go direct */1.297 + char *target = mem_get_region( buffer->render_addr );1.298 + glDrawPixels( buffer->width, buffer->height,1.299 + format, type, target );1.300 + }1.301 +}
.