1.1 --- a/src/pvr2/pvr2mem.c Mon Jan 22 11:45:37 2007 +0000
1.2 +++ b/src/pvr2/pvr2mem.c Wed Jan 24 08:11:14 2007 +0000
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.8 * PVR2 (Video) VRAM handling routines (mainly for the 64-bit region)
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.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.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.29 + if( width == 2 ) {
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.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.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.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.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.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.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.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.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.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.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.131 +void pvr2_vram64_read_twiddled_4( char *dest, sh4addr_t srcaddr, uint32_t width, uint32_t height )
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.139 + srcaddr = srcaddr & 0x7FFFF8;
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.149 + banks[0] += offset_flag;
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.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.159 + } else if( width == 1 ) {
1.160 + *wdest = *banks[0];
1.162 + pvr2_vram64_detwiddle_4( wdest, banks, offset_flag, 0, 0, width, stride );
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.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.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.186 +void pvr2_render_buffer_copy_to_sh4( pvr2_render_buffer_t buffer,
1.187 + gboolean backBuffer )
1.189 + if( buffer->render_addr == -1 )
1.191 + GLenum type, format = GL_BGRA;
1.192 + int line_size = buffer->width, size;
1.194 + switch( buffer->colour_format ) {
1.195 + case COLFMT_RGB565:
1.196 + type = GL_UNSIGNED_SHORT_5_6_5;
1.200 + case COLFMT_RGB888:
1.201 + type = GL_UNSIGNED_BYTE;
1.203 + line_size = (line_size<<1)+line_size;
1.205 + case COLFMT_ARGB1555:
1.206 + type = GL_UNSIGNED_SHORT_5_5_5_1;
1.209 + case COLFMT_ARGB4444:
1.210 + type = GL_UNSIGNED_SHORT_4_4_4_4;
1.213 + case COLFMT_ARGB8888:
1.214 + type = GL_UNSIGNED_INT_8_8_8_8;
1.218 + size = line_size * buffer->height;
1.220 + if( backBuffer ) {
1.222 + glReadBuffer( GL_BACK );
1.224 + glReadBuffer( GL_FRONT );
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.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.242 + * Copy data from PVR ram into the GL render buffer.
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.249 +void pvr2_render_buffer_copy_from_sh4( pvr2_render_buffer_t buffer,
1.250 + gboolean backBuffer )
1.252 + if( buffer->render_addr == -1 )
1.254 + GLenum type, format = GL_RGBA;
1.255 + int size = buffer->width * buffer->height;
1.257 + switch( buffer->colour_format ) {
1.258 + case COLFMT_RGB565:
1.259 + type = GL_UNSIGNED_SHORT_5_6_5;
1.263 + case COLFMT_RGB888:
1.264 + type = GL_UNSIGNED_BYTE;
1.266 + size = (size<<1)+size;
1.268 + case COLFMT_ARGB1555:
1.269 + type = GL_UNSIGNED_SHORT_5_5_5_1;
1.272 + case COLFMT_ARGB4444:
1.273 + type = GL_UNSIGNED_SHORT_4_4_4_4;
1.276 + case COLFMT_ARGB8888:
1.277 + type = GL_UNSIGNED_INT_8_8_8_8;
1.282 + if( backBuffer ) {
1.283 + glDrawBuffer( GL_BACK );
1.285 + glDrawBuffer( GL_FRONT );
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.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 );