Search
lxdream.org :: lxdream/src/pvr2/pvr2mem.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/pvr2mem.c
changeset 315:2d8ba198d62c
prev310:00cd8897ad5e
next325:5717ae5d4746
author nkeynes
date Wed Jan 24 08:11:14 2007 +0000 (17 years ago)
permissions -rw-r--r--
last change Add support for quads (auto-calculated 4th vertex)
view annotate diff log raw
     1 /**
     2  * $Id: pvr2mem.c,v 1.5 2007-01-23 11:19:32 nkeynes Exp $
     3  *
     4  * PVR2 (Video) VRAM handling routines (mainly for the 64-bit region)
     5  *
     6  * Copyright (c) 2005 Nathan Keynes.
     7  *
     8  * This program is free software; you can redistribute it and/or modify
     9  * it under the terms of the GNU General Public License as published by
    10  * the Free Software Foundation; either version 2 of the License, or
    11  * (at your option) any later version.
    12  *
    13  * This program is distributed in the hope that it will be useful,
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16  * GNU General Public License for more details.
    17  */
    18 #include "pvr2.h"
    19 #include <stdio.h>
    20 #include <errno.h>
    22 extern char *video_base;
    24 void pvr2_vram64_write( sh4addr_t destaddr, char *src, uint32_t length )
    25 {
    26     int bank_flag = (destaddr & 0x04) >> 2;
    27     uint32_t *banks[2];
    28     uint32_t *dwsrc;
    29     int i;
    31     destaddr = destaddr & 0x7FFFFF;
    32     if( destaddr + length > 0x800000 ) {
    33 	length = 0x800000 - destaddr;
    34     }
    36     for( i=destaddr & 0xFFFFF000; i < destaddr + length; i+= PAGE_SIZE ) {
    37 	texcache_invalidate_page( i );
    38     }
    40     banks[0] = ((uint32_t *)(video_base + ((destaddr & 0x007FFFF8) >>1)));
    41     banks[1] = banks[0] + 0x100000;
    42     if( bank_flag ) 
    43 	banks[0]++;
    45     /* Handle non-aligned start of source */
    46     if( destaddr & 0x03 ) {
    47 	char *dest = ((char *)banks[bank_flag]) + (destaddr & 0x03);
    48 	for( i= destaddr & 0x03; i < 4 && length > 0; i++, length-- ) {
    49 	    *dest++ = *src++;
    50 	}
    51 	bank_flag = !bank_flag;
    52     }
    54     dwsrc = (uint32_t *)src;
    55     while( length >= 4 ) {
    56 	*banks[bank_flag]++ = *dwsrc++;
    57 	bank_flag = !bank_flag;
    58 	length -= 4;
    59     }
    61     /* Handle non-aligned end of source */
    62     if( length ) {
    63 	src = (char *)dwsrc;
    64 	char *dest = (char *)banks[bank_flag];
    65 	while( length-- > 0 ) {
    66 	    *dest++ = *src++;
    67 	}
    68     }  
    69 }
    71 /**
    72  * Write an image to 64-bit vram, with a line-stride different from the line-size.
    73  * The destaddr must be 32-bit aligned, and both line_bytes and line_stride_bytes
    74  * must be multiples of 4.
    75  */
    76 void pvr2_vram64_write_stride( sh4addr_t destaddr, char *src, uint32_t line_bytes, 
    77 			       uint32_t line_stride_bytes, uint32_t line_count )
    78 {
    79     int bank_flag = (destaddr & 0x04) >> 2;
    80     uint32_t *banks[2];
    81     uint32_t *dwsrc;
    82     uint32_t line_gap;
    83     int line_gap_flag;
    84     int i,j;
    86     destaddr = destaddr & 0x7FFFF8;
    87     i = line_stride_bytes - line_bytes;
    88     line_gap_flag = i & 0x04;
    89     line_gap = i >> 3;
    90     line_bytes >>= 2;
    92     for( i=destaddr & 0xFFFFF000; i < destaddr + line_stride_bytes*line_count; i+= PAGE_SIZE ) {
    93 	texcache_invalidate_page( i );
    94     }
    96     banks[0] = (uint32_t *)(video_base + (destaddr >>1));
    97     banks[1] = banks[0] + 0x100000;
    98     if( bank_flag ) 
    99 	banks[0]++;
   101     dwsrc = (uint32_t *)src;
   102     for( i=0; i<line_count; i++ ) {
   103 	for( j=0; j<line_bytes; j++ ) {
   104 	    *banks[bank_flag]++ = *dwsrc++;
   105 	    bank_flag = !bank_flag;
   106 	}
   107 	banks[0] += line_gap;
   108 	banks[1] += line_gap;
   109 	if( line_gap_flag ) {
   110 	    banks[bank_flag]++;
   111 	    bank_flag = !bank_flag;
   112 	}
   113     }    
   114 }
   116 /**
   117  * Read an image from 64-bit vram, with a destination line-stride different from the line-size.
   118  * The srcaddr must be 32-bit aligned, and both line_bytes and line_stride_bytes
   119  * must be multiples of 4. line_stride_bytes must be >= line_bytes.
   120  * This method is used to extract a "stride" texture from vram.
   121  */
   122 void pvr2_vram64_read_stride( char *dest, uint32_t dest_line_bytes, sh4addr_t srcaddr,
   123 				   uint32_t src_line_bytes, uint32_t line_count )
   124 {
   125     int bank_flag = (srcaddr & 0x04) >> 2;
   126     uint32_t *banks[2];
   127     uint32_t *dwdest;
   128     uint32_t dest_line_gap;
   129     uint32_t src_line_gap;
   130     uint32_t line_bytes;
   131     int src_line_gap_flag;
   132     int i,j;
   134     srcaddr = srcaddr & 0x7FFFF8;
   135     if( src_line_bytes <= dest_line_bytes ) {
   136 	dest_line_gap = (dest_line_bytes - src_line_bytes) >> 2;
   137 	src_line_gap = 0;
   138 	src_line_gap_flag = 0;
   139 	line_bytes = src_line_bytes >> 2;
   140     } else {
   141 	i = (src_line_bytes - dest_line_bytes);
   142 	src_line_gap_flag = i & 0x04;
   143 	src_line_gap = i >> 3;
   144 	line_bytes = dest_line_bytes >> 2;
   145     }
   147     banks[0] = (uint32_t *)(video_base + (srcaddr>>1));
   148     banks[1] = banks[0] + 0x100000;
   149     if( bank_flag )
   150 	banks[0]++;
   152     dwdest = (uint32_t *)dest;
   153     for( i=0; i<line_count; i++ ) {
   154 	for( j=0; j<line_bytes; j++ ) {
   155 	    *dwdest++ = *banks[bank_flag]++;
   156 	    bank_flag = !bank_flag;
   157 	}
   158 	dwdest += dest_line_gap;
   159 	banks[0] += src_line_gap;
   160 	banks[1] += src_line_gap;
   161 	if( src_line_gap_flag ) {
   162 	    banks[bank_flag]++;
   163 	    bank_flag = !bank_flag;
   164 	}
   165     }    
   166 }
   169 /**
   170  * @param dest Destination image buffer
   171  * @param banks Source data expressed as two bank pointers
   172  * @param offset Offset into banks[0] specifying where the next byte
   173  *  to read is (0..3)
   174  * @param x1,y1 Destination coordinates
   175  * @param width Width of current destination block
   176  * @param stride Total width of image (ie stride) in bytes
   177  */
   179 static void pvr2_vram64_detwiddle_4( uint8_t *dest, uint8_t *banks[2], int offset,
   180 				     int x1, int y1, int width, int stride )
   181 {
   182     if( width == 2 ) {
   183 	x1 = x1 >> 1;
   184 	uint8_t t1 = *banks[offset<4?0:1]++;
   185 	uint8_t t2 = *banks[offset<3?0:1]++;
   186 	dest[y1*stride + x1] = (t1 & 0x0F) | (t2<<4);
   187 	dest[(y1+1)*stride + x1] = (t1>>4) | (t2&0xF0);
   188     } else if( width == 4 ) {
   189 	pvr2_vram64_detwiddle_4( dest, banks, offset, x1, y1, 2, stride );
   190 	pvr2_vram64_detwiddle_4( dest, banks, offset+2, x1, y1+2, 2, stride );
   191 	pvr2_vram64_detwiddle_4( dest, banks, offset+4, x1+2, y1, 2, stride );
   192 	pvr2_vram64_detwiddle_4( dest, banks, offset+6, x1+2, y1+2, 2, stride );
   194     } else {
   195 	int subdivide = width >> 1;
   196 	pvr2_vram64_detwiddle_4( dest, banks, offset, x1, y1, subdivide, stride );
   197 	pvr2_vram64_detwiddle_4( dest, banks, offset, x1, y1+subdivide, subdivide, stride );
   198 	pvr2_vram64_detwiddle_4( dest, banks, offset, x1+subdivide, y1, subdivide, stride );
   199 	pvr2_vram64_detwiddle_4( dest, banks, offset, x1+subdivide, y1+subdivide, subdivide, stride );
   200     }
   201 }
   203 /**
   204  * @param dest Destination image buffer
   205  * @param banks Source data expressed as two bank pointers
   206  * @param offset Offset into banks[0] specifying where the next byte
   207  *  to read is (0..3)
   208  * @param x1,y1 Destination coordinates
   209  * @param width Width of current destination block
   210  * @param stride Total width of image (ie stride)
   211  */
   213 static void pvr2_vram64_detwiddle_8( uint8_t *dest, uint8_t *banks[2], int offset,
   214 				     int x1, int y1, int width, int stride )
   215 {
   216     if( width == 2 ) {
   217 	dest[y1*stride + x1] = *banks[0]++;
   218 	dest[(y1+1)*stride + x1] = *banks[offset<3?0:1]++;
   219 	dest[y1*stride + x1 + 1] = *banks[offset<2?0:1]++;
   220 	dest[(y1+1)*stride + x1 + 1] = *banks[offset==0?0:1]++;
   221 	uint8_t *tmp = banks[0]; /* swap banks */
   222 	banks[0] = banks[1];
   223 	banks[1] = tmp;
   224     } else {
   225 	int subdivide = width >> 1;
   226 	pvr2_vram64_detwiddle_8( dest, banks, offset, x1, y1, subdivide, stride );
   227 	pvr2_vram64_detwiddle_8( dest, banks, offset, x1, y1+subdivide, subdivide, stride );
   228 	pvr2_vram64_detwiddle_8( dest, banks, offset, x1+subdivide, y1, subdivide, stride );
   229 	pvr2_vram64_detwiddle_8( dest, banks, offset, x1+subdivide, y1+subdivide, subdivide, stride );
   230     }
   231 }
   233 /**
   234  * @param dest Destination image buffer
   235  * @param banks Source data expressed as two bank pointers
   236  * @param offset Offset into banks[0] specifying where the next word
   237  *  to read is (0 or 1)
   238  * @param x1,y1 Destination coordinates
   239  * @param width Width of current destination block
   240  * @param stride Total width of image (ie stride)
   241  */
   243 static void pvr2_vram64_detwiddle_16( uint16_t *dest, uint16_t *banks[2], int offset,
   244 				      int x1, int y1, int width, int stride )
   245 {
   246     if( width == 2 ) {
   247 	dest[y1*stride + x1] = *banks[0]++;
   248 	dest[(y1+1)*stride + x1] = *banks[offset]++;
   249 	dest[y1*stride + x1 + 1] = *banks[1]++;
   250 	dest[(y1+1)*stride + x1 + 1] = *banks[offset^1]++;
   251     } else {
   252 	int subdivide = width >> 1;
   253 	pvr2_vram64_detwiddle_16( dest, banks, offset, x1, y1, subdivide, stride );
   254 	pvr2_vram64_detwiddle_16( dest, banks, offset, x1, y1+subdivide, subdivide, stride );
   255 	pvr2_vram64_detwiddle_16( dest, banks, offset, x1+subdivide, y1, subdivide, stride );
   256 	pvr2_vram64_detwiddle_16( dest, banks, offset, x1+subdivide, y1+subdivide, subdivide, stride );
   257     }
   258 }
   260 /**
   261  * Read an image from 64-bit vram stored as twiddled 4-bit pixels. The 
   262  * image is written out to the destination in detwiddled form.
   263  * @param dest destination buffer, which must be at least width*height/2 in length
   264  * @param srcaddr source address in vram
   265  * @param width image width (must be a power of 2)
   266  * @param height image height (must be a power of 2)
   267  */
   268 void pvr2_vram64_read_twiddled_4( char *dest, sh4addr_t srcaddr, uint32_t width, uint32_t height )
   269 {
   270     int offset_flag = (srcaddr & 0x07);
   271     uint8_t *banks[2];
   272     uint8_t *wdest = (uint8_t*)dest;
   273     uint32_t stride = width >> 1;
   274     int i,j;
   276     srcaddr = srcaddr & 0x7FFFF8;
   278     banks[0] = (uint8_t *)(video_base + (srcaddr>>1));
   279     banks[1] = banks[0] + 0x400000;
   280     if( offset_flag & 0x04 ) { // If source is not 64-bit aligned, swap the banks
   281 	uint8_t *tmp = banks[0];
   282 	banks[0] = banks[1];
   283 	banks[1] = tmp + 4;
   284 	offset_flag &= 0x03;
   285     }
   286     banks[0] += offset_flag;
   288     if( width > height ) {
   289 	for( i=0; i<width; i+=height ) {
   290 	    pvr2_vram64_detwiddle_4( wdest, banks, offset_flag, i, 0, height, stride );
   291 	}
   292     } else if( height > width ) {
   293 	for( i=0; i<height; i+=width ) {
   294 	    pvr2_vram64_detwiddle_4( wdest, banks, offset_flag, 0, i, width, stride );
   295 	}
   296     } else if( width == 1 ) {
   297 	*wdest = *banks[0];
   298     } else {
   299 	pvr2_vram64_detwiddle_4( wdest, banks, offset_flag, 0, 0, width, stride );
   300     }   
   301 }
   303 /**
   304  * Read an image from 64-bit vram stored as twiddled 8-bit pixels. The 
   305  * image is written out to the destination in detwiddled form.
   306  * @param dest destination buffer, which must be at least width*height in length
   307  * @param srcaddr source address in vram
   308  * @param width image width (must be a power of 2)
   309  * @param height image height (must be a power of 2)
   310  */
   311 void pvr2_vram64_read_twiddled_8( char *dest, sh4addr_t srcaddr, uint32_t width, uint32_t height )
   312 {
   313     int offset_flag = (srcaddr & 0x07);
   314     uint8_t *banks[2];
   315     uint8_t *wdest = (uint8_t*)dest;
   316     int i,j;
   318     srcaddr = srcaddr & 0x7FFFF8;
   320     banks[0] = (uint8_t *)(video_base + (srcaddr>>1));
   321     banks[1] = banks[0] + 0x400000;
   322     if( offset_flag & 0x04 ) { // If source is not 64-bit aligned, swap the banks
   323 	uint8_t *tmp = banks[0];
   324 	banks[0] = banks[1];
   325 	banks[1] = tmp + 4;
   326 	offset_flag &= 0x03;
   327     }
   328     banks[0] += offset_flag;
   330     if( width > height ) {
   331 	for( i=0; i<width; i+=height ) {
   332 	    pvr2_vram64_detwiddle_8( wdest, banks, offset_flag, i, 0, height, width );
   333 	}
   334     } else if( height > width ) {
   335 	for( i=0; i<height; i+=width ) {
   336 	    pvr2_vram64_detwiddle_8( wdest, banks, offset_flag, 0, i, width, width );
   337 	}
   338     } else if( width == 1 ) {
   339 	*wdest = *banks[0];
   340     } else {
   341 	pvr2_vram64_detwiddle_8( wdest, banks, offset_flag, 0, 0, width, width );
   342     }   
   343 }
   345 /**
   346  * Read an image from 64-bit vram stored as twiddled 16-bit pixels. The 
   347  * image is written out to the destination in detwiddled form.
   348  * @param dest destination buffer, which must be at least width*height*2 in length
   349  * @param srcaddr source address in vram (must be 16-bit aligned)
   350  * @param width image width (must be a power of 2)
   351  * @param height image height (must be a power of 2)
   352  */
   353 void pvr2_vram64_read_twiddled_16( char *dest, sh4addr_t srcaddr, uint32_t width, uint32_t height ) {
   354     int offset_flag = (srcaddr & 0x06) >> 1;
   355     uint16_t *banks[2];
   356     uint16_t *wdest = (uint16_t*)dest;
   357     int i,j;
   359     srcaddr = srcaddr & 0x7FFFF8;
   361     banks[0] = (uint16_t *)(video_base + (srcaddr>>1));
   362     banks[1] = banks[0] + 0x200000;
   363     if( offset_flag & 0x02 ) { // If source is not 64-bit aligned, swap the banks
   364 	uint16_t *tmp = banks[0];
   365 	banks[0] = banks[1];
   366 	banks[1] = tmp + 2;
   367 	offset_flag &= 0x01;
   368     }
   369     banks[0] += offset_flag;
   372     if( width > height ) {
   373 	for( i=0; i<width; i+=height ) {
   374 	    pvr2_vram64_detwiddle_16( wdest, banks, offset_flag, i, 0, height, width );
   375 	}
   376     } else if( height > width ) {
   377 	for( i=0; i<height; i+=width ) {
   378 	    pvr2_vram64_detwiddle_16( wdest, banks, offset_flag, 0, i, width, width );
   379 	}
   380     } else if( width == 1 ) {
   381 	*wdest = *banks[0];
   382     } else {
   383 	pvr2_vram64_detwiddle_16( wdest, banks, offset_flag, 0, 0, width, width );
   384     }    
   385 }
   387 void pvr2_vram_write_invert( sh4addr_t destaddr, char *src, uint32_t length, uint32_t line_length )
   388 {
   389     char *dest = video_base + (destaddr & 0x007FFFFF);
   390     char *p = src + length - line_length;
   391     while( p >= src ) {
   392 	memcpy( dest, p, line_length );
   393 	p -= line_length;
   394 	dest += line_length;
   395     }
   396 }
   398 void pvr2_vram64_read( char *dest, sh4addr_t srcaddr, uint32_t length )
   399 {
   400     int bank_flag = (srcaddr & 0x04) >> 2;
   401     uint32_t *banks[2];
   402     uint32_t *dwdest;
   403     int i;
   405     srcaddr = srcaddr & 0x7FFFFF;
   406     if( srcaddr + length > 0x800000 )
   407 	length = 0x800000 - srcaddr;
   409     banks[0] = ((uint32_t *)(video_base + ((srcaddr&0x007FFFF8)>>1)));
   410     banks[1] = banks[0] + 0x100000;
   411     if( bank_flag )
   412 	banks[0]++;
   414     /* Handle non-aligned start of source */
   415     if( srcaddr & 0x03 ) {
   416 	char *src = ((char *)banks[bank_flag]) + (srcaddr & 0x03);
   417 	for( i= srcaddr & 0x03; i < 4 && length > 0; i++, length-- ) {
   418 	    *dest++ = *src++;
   419 	}
   420 	bank_flag = !bank_flag;
   421     }
   423     dwdest = (uint32_t *)dest;
   424     while( length >= 4 ) {
   425 	*dwdest++ = *banks[bank_flag]++;
   426 	bank_flag = !bank_flag;
   427 	length -= 4;
   428     }
   430     /* Handle non-aligned end of source */
   431     if( length ) {
   432 	dest = (char *)dwdest;
   433 	char *src = (char *)banks[bank_flag];
   434 	while( length-- > 0 ) {
   435 	    *dest++ = *src++;
   436 	}
   437     }
   438 }
   440 void pvr2_vram64_dump_file( sh4addr_t addr, uint32_t length, gchar *filename )
   441 {
   442     uint32_t tmp[length>>2];
   443     FILE *f = fopen(filename, "wo");
   444     unsigned int i, j;
   446     if( f == NULL ) {
   447 	ERROR( "Unable to write to dump file '%s' (%s)", filename, strerror(errno) );
   448 	return;
   449     }
   450     pvr2_vram64_read( tmp, addr, length );
   451     fprintf( f, "%08X\n", addr );
   452     for( i =0; i<length>>2; i+=8 ) {
   453 	for( j=i; j<i+8; j++ ) {
   454 	    if( j < length )
   455 		fprintf( f, " %08X", tmp[j] );
   456 	    else
   457 		fprintf( f, "         " );
   458 	}
   459 	fprintf( f, "\n" );
   460     }
   461     fclose(f);
   462 }
   464 void pvr2_vram64_dump( sh4addr_t addr, uint32_t length, FILE *f ) 
   465 {
   466     char tmp[length];
   467     pvr2_vram64_read( tmp, addr, length );
   468     fwrite_dump( tmp, length, f );
   469 }
   473 /**
   474  * Flush the indicated render buffer back to PVR. Caller is responsible for
   475  * tracking whether there is actually anything in the buffer.
   476  *
   477  * @param buffer A render buffer indicating the address to store to, and the
   478  * format the data needs to be in.
   479  * @param backBuffer TRUE to flush the back buffer, FALSE for 
   480  * the front buffer.
   481  */
   482 void pvr2_render_buffer_copy_to_sh4( pvr2_render_buffer_t buffer, 
   483 				     gboolean backBuffer )
   484 {
   485     if( buffer->render_addr == -1 )
   486 	return;
   487     GLenum type, format = GL_BGRA;
   488     int line_size = buffer->width, size;
   490     switch( buffer->colour_format ) {
   491     case COLFMT_RGB565: 
   492 	type = GL_UNSIGNED_SHORT_5_6_5; 
   493 	format = GL_BGR; 
   494 	line_size <<= 1;
   495 	break;
   496     case COLFMT_RGB888: 
   497 	type = GL_UNSIGNED_BYTE; 
   498 	format = GL_BGR;
   499 	line_size = (line_size<<1)+line_size;
   500 	break;
   501     case COLFMT_ARGB1555: 
   502 	type = GL_UNSIGNED_SHORT_5_5_5_1; 
   503 	line_size <<= 1;
   504 	break;
   505     case COLFMT_ARGB4444: 
   506 	type = GL_UNSIGNED_SHORT_4_4_4_4; 
   507 	line_size <<= 1;
   508 	break;
   509     case COLFMT_ARGB8888: 
   510 	type = GL_UNSIGNED_INT_8_8_8_8; 
   511 	line_size <<= 2;
   512 	break;
   513     }
   514     size = line_size * buffer->height;
   516     if( backBuffer ) {
   517 	glFinish();
   518 	glReadBuffer( GL_BACK );
   519     } else {
   520 	glReadBuffer( GL_FRONT );
   521     }
   523     if( buffer->render_addr & 0xFF000000 == 0x04000000 ) {
   524 	/* Interlaced buffer. Go the double copy... :( */
   525 	char target[size];
   526 	glReadPixels( 0, 0, buffer->width, buffer->height, format, type, target );
   527 	pvr2_vram64_write( buffer->render_addr, target, size );
   528     } else {
   529 	/* Regular buffer */
   530 	char target[size];
   531 	glReadPixels( 0, 0, buffer->width, buffer->height, format, type, target );
   532 	pvr2_vram_write_invert( buffer->render_addr, target, size, line_size );
   533     }
   534 }
   537 /**
   538  * Copy data from PVR ram into the GL render buffer. 
   539  *
   540  * @param buffer A render buffer indicating the address to read from, and the
   541  * format the data is in.
   542  * @param backBuffer TRUE to write the back buffer, FALSE for 
   543  * the front buffer.
   544  */
   545 void pvr2_render_buffer_copy_from_sh4( pvr2_render_buffer_t buffer, 
   546 				       gboolean backBuffer )
   547 {
   548     if( buffer->render_addr == -1 )
   549 	return;
   550     GLenum type, format = GL_RGBA;
   551     int size = buffer->width * buffer->height;
   553     switch( buffer->colour_format ) {
   554     case COLFMT_RGB565: 
   555 	type = GL_UNSIGNED_SHORT_5_6_5; 
   556 	format = GL_RGB; 
   557 	size <<= 1;
   558 	break;
   559     case COLFMT_RGB888: 
   560 	type = GL_UNSIGNED_BYTE; 
   561 	format = GL_BGR;
   562 	size = (size<<1)+size;
   563 	break;
   564     case COLFMT_ARGB1555: 
   565 	type = GL_UNSIGNED_SHORT_5_5_5_1; 
   566 	size <<= 1;
   567 	break;
   568     case COLFMT_ARGB4444: 
   569 	type = GL_UNSIGNED_SHORT_4_4_4_4; 
   570 	size <<= 1;
   571 	break;
   572     case COLFMT_ARGB8888: 
   573 	type = GL_UNSIGNED_INT_8_8_8_8; 
   574 	size <<= 2;
   575 	break;
   576     }
   578     if( backBuffer ) {
   579 	glDrawBuffer( GL_BACK );
   580     } else {
   581 	glDrawBuffer( GL_FRONT );
   582     }
   584     glRasterPos2i( 0, 0 );
   585     if( buffer->render_addr & 0xFF000000 == 0x04000000 ) {
   586 	/* Interlaced buffer. Go the double copy... :( */
   587 	char target[size];
   588 	pvr2_vram64_read( target, buffer->render_addr, size );
   589 	glDrawPixels( buffer->width, buffer->height, 
   590 		      format, type, target );
   591     } else {
   592 	/* Regular buffer - go direct */
   593 	char *target = mem_get_region( buffer->render_addr );
   594 	glDrawPixels( buffer->width, buffer->height, 
   595 		      format, type, target );
   596     }
   597 }
.