Search
lxdream.org :: lxdream/src/pvr2/render.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/render.c
changeset 219:dfd3292143f2
prev191:df4441cf3128
next221:cf5c6d326162
author nkeynes
date Tue Aug 29 08:12:13 2006 +0000 (13 years ago)
permissions -rw-r--r--
last change Initial implementation of new background support
file annotate diff log raw
nkeynes@100
     1
/**
nkeynes@219
     2
 * $Id: render.c,v 1.13 2006-08-29 08:12:13 nkeynes Exp $
nkeynes@100
     3
 *
nkeynes@189
     4
 * PVR2 Renderer support. This part is primarily
nkeynes@100
     5
 *
nkeynes@100
     6
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@100
     7
 *
nkeynes@100
     8
 * This program is free software; you can redistribute it and/or modify
nkeynes@100
     9
 * it under the terms of the GNU General Public License as published by
nkeynes@100
    10
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@100
    11
 * (at your option) any later version.
nkeynes@100
    12
 *
nkeynes@100
    13
 * This program is distributed in the hope that it will be useful,
nkeynes@100
    14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@100
    15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@100
    16
 * GNU General Public License for more details.
nkeynes@100
    17
 */
nkeynes@100
    18
nkeynes@100
    19
#include "pvr2/pvr2.h"
nkeynes@100
    20
#include "asic.h"
nkeynes@103
    21
nkeynes@103
    22
static int pvr2_render_colour_format[8] = {
nkeynes@103
    23
    COLFMT_ARGB1555, COLFMT_RGB565, COLFMT_ARGB4444, COLFMT_ARGB1555,
nkeynes@103
    24
    COLFMT_RGB888, COLFMT_ARGB8888, COLFMT_ARGB8888, COLFMT_ARGB4444 };
nkeynes@103
    25
nkeynes@100
    26
nkeynes@100
    27
/**
nkeynes@103
    28
 * Describes a rendering buffer that's actually held in GL, for when we need
nkeynes@103
    29
 * to fetch the bits back to vram.
nkeynes@103
    30
 */
nkeynes@103
    31
typedef struct pvr2_render_buffer {
nkeynes@161
    32
    sh4addr_t render_addr; /* The actual address rendered to in pvr ram */
nkeynes@161
    33
    uint32_t size; /* Length of rendering region in bytes */
nkeynes@103
    34
    int width, height;
nkeynes@103
    35
    int colour_format;
nkeynes@103
    36
} *pvr2_render_buffer_t;
nkeynes@103
    37
nkeynes@103
    38
struct pvr2_render_buffer front_buffer;
nkeynes@103
    39
struct pvr2_render_buffer back_buffer;
nkeynes@103
    40
nkeynes@128
    41
typedef struct pvr2_bgplane_packed {
nkeynes@128
    42
        uint32_t        poly_cfg, poly_mode;
nkeynes@128
    43
        uint32_t        texture_mode;
nkeynes@128
    44
        float           x1, y1, z1;
nkeynes@128
    45
        uint32_t          colour1;
nkeynes@128
    46
        float           x2, y2, z2;
nkeynes@128
    47
        uint32_t          colour2;
nkeynes@128
    48
        float           x3, y3, z3;
nkeynes@128
    49
        uint32_t          colour3;
nkeynes@128
    50
} *pvr2_bgplane_packed_t;
nkeynes@128
    51
nkeynes@128
    52
nkeynes@103
    53
nkeynes@103
    54
void pvr2_render_copy_to_sh4( pvr2_render_buffer_t buffer, 
nkeynes@103
    55
			      gboolean backBuffer );
nkeynes@103
    56
nkeynes@108
    57
int pvr2_render_font_list = -1;
nkeynes@132
    58
int pvr2_render_trace = 0;
nkeynes@108
    59
nkeynes@132
    60
int glPrintf( int x, int y, const char *fmt, ... )
nkeynes@108
    61
{
nkeynes@108
    62
    va_list ap;     /* our argument pointer */
nkeynes@108
    63
    char buf[256];
nkeynes@108
    64
    int len;
nkeynes@108
    65
    if (fmt == NULL)    /* if there is no string to draw do nothing */
nkeynes@108
    66
        return;
nkeynes@108
    67
    va_start(ap, fmt); 
nkeynes@108
    68
    len = vsnprintf(buf, sizeof(buf), fmt, ap);
nkeynes@108
    69
    va_end(ap);
nkeynes@108
    70
nkeynes@108
    71
nkeynes@108
    72
    glPushAttrib(GL_LIST_BIT);
nkeynes@132
    73
    glDisable( GL_DEPTH_TEST );
nkeynes@132
    74
    glDisable( GL_BLEND );
nkeynes@132
    75
    glDisable( GL_TEXTURE_2D );
nkeynes@132
    76
    glDisable( GL_ALPHA_TEST );
nkeynes@189
    77
    glDisable( GL_CULL_FACE );
nkeynes@108
    78
    glListBase(pvr2_render_font_list - 32);
nkeynes@132
    79
    glColor3f( 1.0, 1.0, 1.0 );
nkeynes@132
    80
    glRasterPos2i( x, y );
nkeynes@108
    81
    glCallLists(len, GL_UNSIGNED_BYTE, buf);
nkeynes@108
    82
    glPopAttrib();
nkeynes@108
    83
nkeynes@108
    84
    return len;
nkeynes@108
    85
}
nkeynes@108
    86
nkeynes@189
    87
void glDrawGrid( int width, int height )
nkeynes@189
    88
{
nkeynes@189
    89
    int i;
nkeynes@189
    90
    glDisable( GL_DEPTH_TEST );
nkeynes@189
    91
    glLineWidth(1);
nkeynes@189
    92
    
nkeynes@189
    93
    glBegin( GL_LINES );
nkeynes@189
    94
    glColor4f( 1.0, 1.0, 1.0, 1.0 );
nkeynes@189
    95
    for( i=32; i<width; i+=32 ) {
nkeynes@189
    96
	glVertex3f( i, 0.0, 3.0 );
nkeynes@189
    97
	glVertex3f( i,height-1, 3.0 );
nkeynes@189
    98
    }
nkeynes@189
    99
nkeynes@189
   100
    for( i=32; i<height; i+=32 ) {
nkeynes@189
   101
	glVertex3f( 0.0, i, 3.0 );
nkeynes@189
   102
	glVertex3f( width, i, 3.0 );
nkeynes@189
   103
    }
nkeynes@189
   104
    glEnd();
nkeynes@189
   105
	
nkeynes@189
   106
}
nkeynes@189
   107
nkeynes@103
   108
nkeynes@103
   109
gboolean pvr2_render_init( void )
nkeynes@103
   110
{
nkeynes@103
   111
    front_buffer.render_addr = -1;
nkeynes@103
   112
    back_buffer.render_addr = -1;
nkeynes@103
   113
}
nkeynes@103
   114
nkeynes@103
   115
/**
nkeynes@161
   116
 * Invalidate any caching on the supplied address. Specifically, if it falls
nkeynes@161
   117
 * within either the front buffer or back buffer, flush the buffer back to
nkeynes@161
   118
 * PVR2 ram (note that front buffer flush may be corrupt under some
nkeynes@161
   119
 * circumstances).
nkeynes@161
   120
 */
nkeynes@161
   121
gboolean pvr2_render_invalidate( sh4addr_t address )
nkeynes@161
   122
{
nkeynes@161
   123
    address = address & 0x1FFFFFFF;
nkeynes@161
   124
    if( front_buffer.render_addr != -1 &&
nkeynes@161
   125
	front_buffer.render_addr <= address &&
nkeynes@161
   126
	(front_buffer.render_addr + front_buffer.size) > address ) {
nkeynes@161
   127
	pvr2_render_copy_to_sh4( &front_buffer, FALSE );
nkeynes@161
   128
	front_buffer.render_addr = -1;
nkeynes@161
   129
	return TRUE;
nkeynes@161
   130
    } else if( back_buffer.render_addr != -1 &&
nkeynes@161
   131
	       back_buffer.render_addr <= address &&
nkeynes@161
   132
	       (back_buffer.render_addr + back_buffer.size) > address ) {
nkeynes@161
   133
	pvr2_render_copy_to_sh4( &back_buffer, TRUE );
nkeynes@161
   134
	back_buffer.render_addr = -1;
nkeynes@161
   135
	return TRUE;
nkeynes@161
   136
    }
nkeynes@161
   137
    return FALSE;
nkeynes@161
   138
}
nkeynes@161
   139
nkeynes@161
   140
/**
nkeynes@103
   141
 * Display a rendered frame if one is available.
nkeynes@103
   142
 * @param address An address in PVR ram (0500000 range).
nkeynes@103
   143
 * @return TRUE if a frame was available to be displayed, otherwise false.
nkeynes@103
   144
 */
nkeynes@103
   145
gboolean pvr2_render_display_frame( uint32_t address )
nkeynes@103
   146
{
nkeynes@103
   147
    if( front_buffer.render_addr == address ) {
nkeynes@103
   148
	/* Current front buffer is already displayed, so do nothing
nkeynes@103
   149
	 * and tell the caller that all is well.
nkeynes@103
   150
	 */
nkeynes@103
   151
	return TRUE;
nkeynes@103
   152
    }
nkeynes@103
   153
    if( back_buffer.render_addr == address ) {
nkeynes@103
   154
	/* The more useful case - back buffer is to be displayed. Swap
nkeynes@103
   155
	 * the buffers 
nkeynes@103
   156
	 */
nkeynes@144
   157
	display_driver->display_back_buffer();
nkeynes@103
   158
	front_buffer = back_buffer;
nkeynes@103
   159
	back_buffer.render_addr = -1;
nkeynes@103
   160
	return TRUE;
nkeynes@103
   161
    }
nkeynes@103
   162
    return FALSE;
nkeynes@108
   163
}	
nkeynes@103
   164
nkeynes@103
   165
/**
nkeynes@103
   166
 * Prepare the OpenGL context to receive instructions for a new frame.
nkeynes@103
   167
 */
nkeynes@103
   168
static void pvr2_render_prepare_context( sh4addr_t render_addr, 
nkeynes@103
   169
					 uint32_t width, uint32_t height,
nkeynes@103
   170
					 uint32_t colour_format, 
nkeynes@128
   171
					 float bgplanez,
nkeynes@103
   172
					 gboolean texture_target )
nkeynes@103
   173
{
nkeynes@103
   174
    /* Select and initialize the render context */
nkeynes@144
   175
    display_driver->set_render_format( width, height, colour_format, texture_target );
nkeynes@103
   176
nkeynes@132
   177
    if( pvr2_render_font_list == -1 ) {
nkeynes@132
   178
	pvr2_render_font_list = video_glx_load_font( "-*-helvetica-*-r-normal--16-*-*-*-p-*-iso8859-1");
nkeynes@132
   179
    }
nkeynes@132
   180
nkeynes@103
   181
    if( back_buffer.render_addr != -1 && 
nkeynes@103
   182
	back_buffer.render_addr != render_addr ) {
nkeynes@103
   183
	/* There's a current back buffer, and we're rendering somewhere else -
nkeynes@103
   184
	 * flush the back buffer back to vram and start a new back buffer
nkeynes@103
   185
	 */
nkeynes@103
   186
	pvr2_render_copy_to_sh4( &back_buffer, TRUE );
nkeynes@103
   187
    }
nkeynes@103
   188
nkeynes@103
   189
    if( front_buffer.render_addr == render_addr ) {
nkeynes@103
   190
	/* In case we've been asked to render to the current front buffer -
nkeynes@103
   191
	 * invalidate the front buffer and render to the back buffer, ensuring
nkeynes@103
   192
	 * we swap at the next frame display.
nkeynes@103
   193
	 */
nkeynes@103
   194
	front_buffer.render_addr = -1;
nkeynes@103
   195
    }
nkeynes@103
   196
    back_buffer.render_addr = render_addr;
nkeynes@103
   197
    back_buffer.width = width;
nkeynes@103
   198
    back_buffer.height = height;
nkeynes@103
   199
    back_buffer.colour_format = colour_format;
nkeynes@161
   200
    back_buffer.size = width * height * colour_format_bytes[colour_format];
nkeynes@103
   201
nkeynes@103
   202
    /* Setup the display model */
nkeynes@103
   203
    glDrawBuffer(GL_BACK);
nkeynes@103
   204
    glShadeModel(GL_SMOOTH);
nkeynes@103
   205
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
nkeynes@103
   206
    glViewport( 0, 0, width, height );
nkeynes@103
   207
    glMatrixMode(GL_PROJECTION);
nkeynes@103
   208
    glLoadIdentity();
nkeynes@169
   209
    glOrtho( 0, width, height, 0, bgplanez, -4 );
nkeynes@103
   210
    glMatrixMode(GL_MODELVIEW);
nkeynes@103
   211
    glLoadIdentity();
nkeynes@108
   212
    glCullFace( GL_BACK );
nkeynes@103
   213
nkeynes@103
   214
    /* Clear out the buffers */
nkeynes@189
   215
    glDisable( GL_SCISSOR_TEST );
nkeynes@103
   216
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
nkeynes@128
   217
    glClearDepth(bgplanez);
nkeynes@103
   218
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
nkeynes@103
   219
}
nkeynes@103
   220
nkeynes@103
   221
nkeynes@128
   222
#define MIN3( a,b,c ) ((a) < (b) ? ( (a) < (c) ? (a) : (c) ) : ((b) < (c) ? (b) : (c)) )
nkeynes@128
   223
#define MAX3( a,b,c ) ((a) > (b) ? ( (a) > (c) ? (a) : (c) ) : ((b) > (c) ? (b) : (c)) )
nkeynes@128
   224
nkeynes@128
   225
/**
nkeynes@103
   226
 * Render a complete scene into the OpenGL back buffer.
nkeynes@103
   227
 * Note: this will probably need to be broken up eventually once timings are
nkeynes@100
   228
 * determined.
nkeynes@100
   229
 */
nkeynes@103
   230
void pvr2_render_scene( )
nkeynes@100
   231
{
nkeynes@103
   232
    struct tile_descriptor *tile_desc =
nkeynes@191
   233
	(struct tile_descriptor *)mem_get_region(PVR2_RAM_BASE + MMIO_READ( PVR2, RENDER_TILEBASE ));
nkeynes@100
   234
nkeynes@191
   235
    uint32_t render_addr = MMIO_READ( PVR2, RENDER_ADDR1 );
nkeynes@103
   236
    gboolean render_to_tex;
nkeynes@103
   237
    if( render_addr & 0x01000000 ) {
nkeynes@103
   238
	render_addr = (render_addr & 0x00FFFFFF) + PVR2_RAM_BASE_INT;
nkeynes@103
   239
	/* Heuristic - if we're rendering to the interlaced region we're
nkeynes@103
   240
	 * probably creating a texture rather than rendering actual output.
nkeynes@103
   241
	 * We can optimise for this case a little
nkeynes@103
   242
	 */
nkeynes@103
   243
	render_to_tex = TRUE;
nkeynes@118
   244
	WARN( "Render to texture not supported properly yet" );
nkeynes@103
   245
    } else {
nkeynes@103
   246
	render_addr = (render_addr & 0x00FFFFFF) + PVR2_RAM_BASE;
nkeynes@103
   247
	render_to_tex = FALSE;
nkeynes@103
   248
    }
nkeynes@128
   249
    
nkeynes@191
   250
    float bgplanez = MMIO_READF( PVR2, RENDER_FARCLIP );
nkeynes@191
   251
    uint32_t render_mode = MMIO_READ( PVR2, RENDER_MODE );
nkeynes@103
   252
    int width = 640; /* FIXME - get this from the tile buffer */
nkeynes@103
   253
    int height = 480;
nkeynes@103
   254
    int colour_format = pvr2_render_colour_format[render_mode&0x07];
nkeynes@103
   255
    pvr2_render_prepare_context( render_addr, width, height, colour_format, 
nkeynes@128
   256
				 bgplanez, render_to_tex );
nkeynes@103
   257
nkeynes@191
   258
    int clip_x = MMIO_READ( PVR2, RENDER_HCLIP ) & 0x03FF;
nkeynes@191
   259
    int clip_y = MMIO_READ( PVR2, RENDER_VCLIP ) & 0x03FF;
nkeynes@191
   260
    int clip_width = ((MMIO_READ( PVR2, RENDER_HCLIP ) >> 16) & 0x03FF) - clip_x + 1;
nkeynes@191
   261
    int clip_height= ((MMIO_READ( PVR2, RENDER_VCLIP ) >> 16) & 0x03FF) - clip_y + 1;
nkeynes@103
   262
nkeynes@103
   263
    /* Fog setup goes here */
nkeynes@103
   264
nkeynes@128
   265
    /* Render the background plane */
nkeynes@191
   266
    uint32_t bgplane_mode = MMIO_READ(PVR2, RENDER_BGPLANE);
nkeynes@189
   267
    uint32_t *display_list = 
nkeynes@191
   268
	(uint32_t *)mem_get_region(PVR2_RAM_BASE + MMIO_READ( PVR2, RENDER_POLYBASE ));
nkeynes@189
   269
nkeynes@189
   270
    uint32_t *bgplane = display_list + (((bgplane_mode & 0x00FFFFFF)) >> 3) ;
nkeynes@219
   271
    render_backplane( bgplane, width, height, bgplane_mode );
nkeynes@128
   272
nkeynes@189
   273
    pvr2_render_tilebuffer( width, height, clip_x, clip_y, 
nkeynes@189
   274
			    clip_x + clip_width, clip_y + clip_height );
nkeynes@103
   275
nkeynes@103
   276
    /* Post-render cleanup and update */
nkeynes@103
   277
nkeynes@108
   278
    /* Add frame, fps, etc data */
nkeynes@189
   279
    //glDrawGrid( width, height );
nkeynes@132
   280
    glPrintf( 4, 16, "Frame %d", pvr2_get_frame_count() );
nkeynes@103
   281
    /* Generate end of render event */
nkeynes@100
   282
    asic_event( EVENT_PVR_RENDER_DONE );
nkeynes@132
   283
    DEBUG( "Rendered frame %d", pvr2_get_frame_count() );
nkeynes@100
   284
}
nkeynes@103
   285
nkeynes@103
   286
nkeynes@103
   287
/**
nkeynes@103
   288
 * Flush the indicated render buffer back to PVR. Caller is responsible for
nkeynes@103
   289
 * tracking whether there is actually anything in the buffer.
nkeynes@103
   290
 *
nkeynes@103
   291
 * @param buffer A render buffer indicating the address to store to, and the
nkeynes@103
   292
 * format the data needs to be in.
nkeynes@103
   293
 * @param backBuffer TRUE to flush the back buffer, FALSE for 
nkeynes@103
   294
 * the front buffer.
nkeynes@103
   295
 */
nkeynes@103
   296
void pvr2_render_copy_to_sh4( pvr2_render_buffer_t buffer, 
nkeynes@103
   297
			      gboolean backBuffer )
nkeynes@103
   298
{
nkeynes@103
   299
    if( buffer->render_addr == -1 )
nkeynes@103
   300
	return;
nkeynes@103
   301
    GLenum type, format = GL_RGBA;
nkeynes@219
   302
    int line_size = buffer->width, size;
nkeynes@103
   303
nkeynes@103
   304
    switch( buffer->colour_format ) {
nkeynes@103
   305
    case COLFMT_RGB565: 
nkeynes@103
   306
	type = GL_UNSIGNED_SHORT_5_6_5; 
nkeynes@103
   307
	format = GL_RGB; 
nkeynes@219
   308
	line_size <<= 1;
nkeynes@103
   309
	break;
nkeynes@103
   310
    case COLFMT_RGB888: 
nkeynes@103
   311
	type = GL_UNSIGNED_INT; 
nkeynes@103
   312
	format = GL_RGB;
nkeynes@219
   313
	line_size = (line_size<<1)+line_size;
nkeynes@103
   314
	break;
nkeynes@103
   315
    case COLFMT_ARGB1555: 
nkeynes@103
   316
	type = GL_UNSIGNED_SHORT_5_5_5_1; 
nkeynes@219
   317
	line_size <<= 1;
nkeynes@103
   318
	break;
nkeynes@103
   319
    case COLFMT_ARGB4444: 
nkeynes@103
   320
	type = GL_UNSIGNED_SHORT_4_4_4_4; 
nkeynes@219
   321
	line_size <<= 1;
nkeynes@103
   322
	break;
nkeynes@103
   323
    case COLFMT_ARGB8888: 
nkeynes@103
   324
	type = GL_UNSIGNED_INT_8_8_8_8; 
nkeynes@219
   325
	line_size <<= 2;
nkeynes@103
   326
	break;
nkeynes@103
   327
    }
nkeynes@219
   328
    size = line_size * buffer->height;
nkeynes@103
   329
    
nkeynes@103
   330
    if( backBuffer ) {
nkeynes@103
   331
	glFinish();
nkeynes@103
   332
	glReadBuffer( GL_BACK );
nkeynes@103
   333
    } else {
nkeynes@103
   334
	glReadBuffer( GL_FRONT );
nkeynes@103
   335
    }
nkeynes@103
   336
nkeynes@103
   337
    if( buffer->render_addr & 0xFF000000 == 0x04000000 ) {
nkeynes@103
   338
	/* Interlaced buffer. Go the double copy... :( */
nkeynes@103
   339
	char target[size];
nkeynes@103
   340
	glReadPixels( 0, 0, buffer->width, buffer->height, format, type, target );
nkeynes@103
   341
	pvr2_vram64_write( buffer->render_addr, target, size );
nkeynes@103
   342
    } else {
nkeynes@219
   343
	/* Regular buffer */
nkeynes@219
   344
	char target[size];
nkeynes@103
   345
	glReadPixels( 0, 0, buffer->width, buffer->height, format, type, target );
nkeynes@219
   346
	pvr2_vram_write_invert( buffer->render_addr, target, size, line_size );
nkeynes@103
   347
    }
nkeynes@103
   348
}
nkeynes@103
   349
nkeynes@103
   350
nkeynes@103
   351
/**
nkeynes@103
   352
 * Copy data from PVR ram into the GL render buffer. 
nkeynes@103
   353
 *
nkeynes@103
   354
 * @param buffer A render buffer indicating the address to read from, and the
nkeynes@103
   355
 * format the data is in.
nkeynes@103
   356
 * @param backBuffer TRUE to write the back buffer, FALSE for 
nkeynes@103
   357
 * the front buffer.
nkeynes@103
   358
 */
nkeynes@103
   359
void pvr2_render_copy_from_sh4( pvr2_render_buffer_t buffer, 
nkeynes@103
   360
				gboolean backBuffer )
nkeynes@103
   361
{
nkeynes@103
   362
    if( buffer->render_addr == -1 )
nkeynes@103
   363
	return;
nkeynes@103
   364
    GLenum type, format = GL_RGBA;
nkeynes@103
   365
    int size = buffer->width * buffer->height;
nkeynes@103
   366
nkeynes@103
   367
    switch( buffer->colour_format ) {
nkeynes@103
   368
    case COLFMT_RGB565: 
nkeynes@103
   369
	type = GL_UNSIGNED_SHORT_5_6_5; 
nkeynes@103
   370
	format = GL_RGB; 
nkeynes@103
   371
	size <<= 1;
nkeynes@103
   372
	break;
nkeynes@103
   373
    case COLFMT_RGB888: 
nkeynes@103
   374
	type = GL_UNSIGNED_INT; 
nkeynes@103
   375
	format = GL_RGB;
nkeynes@103
   376
	size = (size<<1)+size;
nkeynes@103
   377
	break;
nkeynes@103
   378
    case COLFMT_ARGB1555: 
nkeynes@103
   379
	type = GL_UNSIGNED_SHORT_5_5_5_1; 
nkeynes@103
   380
	size <<= 1;
nkeynes@103
   381
	break;
nkeynes@103
   382
    case COLFMT_ARGB4444: 
nkeynes@103
   383
	type = GL_UNSIGNED_SHORT_4_4_4_4; 
nkeynes@103
   384
	size <<= 1;
nkeynes@103
   385
	break;
nkeynes@103
   386
    case COLFMT_ARGB8888: 
nkeynes@103
   387
	type = GL_UNSIGNED_INT_8_8_8_8; 
nkeynes@103
   388
	size <<= 2;
nkeynes@103
   389
	break;
nkeynes@103
   390
    }
nkeynes@103
   391
    
nkeynes@103
   392
    if( backBuffer ) {
nkeynes@103
   393
	glDrawBuffer( GL_BACK );
nkeynes@103
   394
    } else {
nkeynes@103
   395
	glDrawBuffer( GL_FRONT );
nkeynes@103
   396
    }
nkeynes@103
   397
nkeynes@103
   398
    glRasterPos2i( 0, 0 );
nkeynes@103
   399
    if( buffer->render_addr & 0xFF000000 == 0x04000000 ) {
nkeynes@103
   400
	/* Interlaced buffer. Go the double copy... :( */
nkeynes@103
   401
	char target[size];
nkeynes@103
   402
	pvr2_vram64_read( target, buffer->render_addr, size );
nkeynes@103
   403
	glDrawPixels( buffer->width, buffer->height, 
nkeynes@103
   404
		      format, type, target );
nkeynes@103
   405
    } else {
nkeynes@103
   406
	/* Regular buffer - go direct */
nkeynes@103
   407
	char *target = mem_get_region( buffer->render_addr );
nkeynes@103
   408
	glDrawPixels( buffer->width, buffer->height, 
nkeynes@103
   409
		      format, type, target );
nkeynes@103
   410
    }
nkeynes@103
   411
}
.