Search
lxdream.org :: lxdream/src/pvr2/pvr2mem.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/pvr2mem.c
changeset 315:2d8ba198d62c
prev310:00cd8897ad5e
next325:5717ae5d4746
author nkeynes
date Tue Jan 23 11:19:32 2007 +0000 (12 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 +0000
1.2 +++ b/src/pvr2/pvr2mem.c Tue Jan 23 11:19:32 2007 +0000
1.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.13
1.14 +
1.15 /**
1.16 * @param dest Destination image buffer
1.17 * @param banks Source data expressed as two bank pointers
1.18 @@ -172,26 +173,60 @@
1.19 * to read is (0..3)
1.20 * @param x1,y1 Destination coordinates
1.21 * @param width Width of current destination block
1.22 - * @param image_width Total width of image (ie stride)
1.23 + * @param stride Total width of image (ie stride) in bytes
1.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 buffer
1.52 + * @param banks Source data expressed as two bank pointers
1.53 + * @param offset Offset into banks[0] specifying where the next byte
1.54 + * to read is (0..3)
1.55 + * @param x1,y1 Destination coordinates
1.56 + * @param width Width of current destination block
1.57 + * @param stride Total width of image (ie stride)
1.58 */
1.59
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.88
1.89 @@ -202,27 +237,70 @@
1.90 * to read is (0 or 1)
1.91 * @param x1,y1 Destination coordinates
1.92 * @param width Width of current destination block
1.93 - * @param image_width Total width of image (ie stride)
1.94 + * @param stride Total width of image (ie stride)
1.95 */
1.96
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.122
1.123 /**
1.124 + * Read an image from 64-bit vram stored as twiddled 4-bit pixels. The
1.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 length
1.127 + * @param srcaddr source address in vram
1.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 banks
1.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. The
1.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 length
1.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 for
1.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 the
1.182 + * format the data needs to be in.
1.183 + * @param backBuffer TRUE to flush the back buffer, FALSE for
1.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 the
1.245 + * format the data is in.
1.246 + * @param backBuffer TRUE to write the back buffer, FALSE for
1.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 +}
.