filename | src/pvr2/render.c |
changeset | 161:408b9210395f |
prev | 144:7f0714e89aaa |
next | 169:abbdc6943587 |
author | nkeynes |
date | Mon Jun 19 11:00:42 2006 +0000 (17 years ago) |
permissions | -rw-r--r-- |
last change | Add config value retrieval for pathnames Implement default path for disc + save state loaders Dump disc ID when mounting a CD |
view | annotate | diff | log | raw |
1 /**
2 * $Id: render.c,v 1.9 2006-06-18 11:57:05 nkeynes Exp $
3 *
4 * PVR2 Renderer support. This is where the real work happens.
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 */
19 #include "pvr2/pvr2.h"
20 #include "asic.h"
23 #define POLY_COLOUR_PACKED 0x00000000
24 #define POLY_COLOUR_FLOAT 0x00000010
25 #define POLY_COLOUR_INTENSITY 0x00000020
26 #define POLY_COLOUR_INTENSITY_PREV 0x00000030
28 static int pvr2_poly_vertexes[4] = { 3, 4, 6, 8 };
29 static int pvr2_poly_type[4] = { GL_TRIANGLES, GL_QUADS, GL_TRIANGLE_STRIP, GL_TRIANGLE_STRIP };
30 static int pvr2_poly_depthmode[8] = { GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL,
31 GL_GREATER, GL_NOTEQUAL, GL_GEQUAL,
32 GL_ALWAYS };
33 static int pvr2_poly_srcblend[8] = {
34 GL_ZERO, GL_ONE, GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR,
35 GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA,
36 GL_ONE_MINUS_DST_ALPHA };
37 static int pvr2_poly_dstblend[8] = {
38 GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR,
39 GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA,
40 GL_ONE_MINUS_DST_ALPHA };
41 static int pvr2_poly_texblend[4] = {
42 GL_REPLACE, GL_BLEND, GL_DECAL, GL_MODULATE };
43 static int pvr2_render_colour_format[8] = {
44 COLFMT_ARGB1555, COLFMT_RGB565, COLFMT_ARGB4444, COLFMT_ARGB1555,
45 COLFMT_RGB888, COLFMT_ARGB8888, COLFMT_ARGB8888, COLFMT_ARGB4444 };
47 #define POLY_STRIP_TYPE(poly) ( pvr2_poly_type[((poly->command)>>18)&0x03] )
48 #define POLY_STRIP_VERTEXES(poly) ( pvr2_poly_vertexes[((poly->command)>>18)&0x03] )
49 #define POLY_DEPTH_MODE(poly) ( pvr2_poly_depthmode[poly->poly_cfg>>29] )
50 #define POLY_DEPTH_WRITE(poly) ((poly->poly_cfg&0x04000000) == 0 )
51 #define POLY_TEX_WIDTH(poly) ( 1<< (((poly->poly_mode >> 3) & 0x07 ) + 3) )
52 #define POLY_TEX_HEIGHT(poly) ( 1<< (((poly->poly_mode) & 0x07 ) + 3) )
53 #define POLY_BLEND_SRC(poly) ( pvr2_poly_srcblend[(poly->poly_mode) >> 29] )
54 #define POLY_BLEND_DEST(poly) ( pvr2_poly_dstblend[((poly->poly_mode)>>26)&0x07] )
55 #define POLY_TEX_BLEND(poly) ( pvr2_poly_texblend[((poly->poly_mode) >> 6)&0x03] )
56 #define POLY_COLOUR_TYPE(poly) ( poly->command & 0x00000030 )
58 /**
59 * Describes a rendering buffer that's actually held in GL, for when we need
60 * to fetch the bits back to vram.
61 */
62 typedef struct pvr2_render_buffer {
63 sh4addr_t render_addr; /* The actual address rendered to in pvr ram */
64 uint32_t size; /* Length of rendering region in bytes */
65 int width, height;
66 int colour_format;
67 } *pvr2_render_buffer_t;
69 struct pvr2_render_buffer front_buffer;
70 struct pvr2_render_buffer back_buffer;
72 struct tile_descriptor {
73 uint32_t header[6];
74 struct tile_pointers {
75 uint32_t tile_id;
76 uint32_t opaque_ptr;
77 uint32_t opaque_mod_ptr;
78 uint32_t trans_ptr;
79 uint32_t trans_mod_ptr;
80 uint32_t punchout_ptr;
81 } tile[0];
82 };
84 /* Textured polygon */
85 struct pvr2_poly {
86 uint32_t command;
87 uint32_t poly_cfg; /* Bitmask */
88 uint32_t poly_mode; /* texture/blending mask */
89 uint32_t texture; /* texture data */
90 float alpha;
91 float red;
92 float green;
93 float blue;
94 };
96 struct pvr2_specular_highlight {
97 float base_alpha;
98 float base_red;
99 float base_green;
100 float base_blue;
101 float offset_alpha;
102 float offset_red;
103 float offset_green;
104 float offset_blue;
105 };
108 struct pvr2_vertex_packed {
109 uint32_t command;
110 float x, y, z;
111 float s,t;
112 uint32_t colour;
113 float f;
114 };
116 struct pvr2_vertex_float {
117 uint32_t command;
118 float x,y,z;
119 float a, r, g, b;
120 };
122 union pvr2_vertex {
123 struct pvr2_vertex_packed pack;
124 struct pvr2_vertex_float flt;
125 };
127 typedef struct pvr2_bgplane_packed {
128 uint32_t poly_cfg, poly_mode;
129 uint32_t texture_mode;
130 float x1, y1, z1;
131 uint32_t colour1;
132 float x2, y2, z2;
133 uint32_t colour2;
134 float x3, y3, z3;
135 uint32_t colour3;
136 } *pvr2_bgplane_packed_t;
140 void pvr2_render_copy_to_sh4( pvr2_render_buffer_t buffer,
141 gboolean backBuffer );
143 int pvr2_render_font_list = -1;
144 int pvr2_render_trace = 0;
146 int glPrintf( int x, int y, const char *fmt, ... )
147 {
148 va_list ap; /* our argument pointer */
149 char buf[256];
150 int len;
151 if (fmt == NULL) /* if there is no string to draw do nothing */
152 return;
153 va_start(ap, fmt);
154 len = vsnprintf(buf, sizeof(buf), fmt, ap);
155 va_end(ap);
158 glPushAttrib(GL_LIST_BIT);
159 glDisable( GL_DEPTH_TEST );
160 glDisable( GL_BLEND );
161 glDisable( GL_TEXTURE_2D );
162 glDisable( GL_ALPHA_TEST );
163 glListBase(pvr2_render_font_list - 32);
164 glColor3f( 1.0, 1.0, 1.0 );
165 glRasterPos2i( x, y );
166 glCallLists(len, GL_UNSIGNED_BYTE, buf);
167 glPopAttrib();
169 return len;
170 }
173 gboolean pvr2_render_init( void )
174 {
175 front_buffer.render_addr = -1;
176 back_buffer.render_addr = -1;
177 }
179 /**
180 * Invalidate any caching on the supplied address. Specifically, if it falls
181 * within either the front buffer or back buffer, flush the buffer back to
182 * PVR2 ram (note that front buffer flush may be corrupt under some
183 * circumstances).
184 */
185 gboolean pvr2_render_invalidate( sh4addr_t address )
186 {
187 address = address & 0x1FFFFFFF;
188 if( front_buffer.render_addr != -1 &&
189 front_buffer.render_addr <= address &&
190 (front_buffer.render_addr + front_buffer.size) > address ) {
191 pvr2_render_copy_to_sh4( &front_buffer, FALSE );
192 front_buffer.render_addr = -1;
193 return TRUE;
194 } else if( back_buffer.render_addr != -1 &&
195 back_buffer.render_addr <= address &&
196 (back_buffer.render_addr + back_buffer.size) > address ) {
197 pvr2_render_copy_to_sh4( &back_buffer, TRUE );
198 back_buffer.render_addr = -1;
199 return TRUE;
200 }
201 return FALSE;
202 }
204 /**
205 * Display a rendered frame if one is available.
206 * @param address An address in PVR ram (0500000 range).
207 * @return TRUE if a frame was available to be displayed, otherwise false.
208 */
209 gboolean pvr2_render_display_frame( uint32_t address )
210 {
211 if( front_buffer.render_addr == address ) {
212 /* Current front buffer is already displayed, so do nothing
213 * and tell the caller that all is well.
214 */
215 return TRUE;
216 }
217 if( back_buffer.render_addr == address ) {
218 /* The more useful case - back buffer is to be displayed. Swap
219 * the buffers
220 */
221 display_driver->display_back_buffer();
222 front_buffer = back_buffer;
223 back_buffer.render_addr = -1;
224 return TRUE;
225 }
226 return FALSE;
227 }
229 /**
230 * Prepare the OpenGL context to receive instructions for a new frame.
231 */
232 static void pvr2_render_prepare_context( sh4addr_t render_addr,
233 uint32_t width, uint32_t height,
234 uint32_t colour_format,
235 float bgplanez,
236 gboolean texture_target )
237 {
238 /* Select and initialize the render context */
239 display_driver->set_render_format( width, height, colour_format, texture_target );
241 if( pvr2_render_font_list == -1 ) {
242 pvr2_render_font_list = video_glx_load_font( "-*-helvetica-*-r-normal--16-*-*-*-p-*-iso8859-1");
243 }
245 if( back_buffer.render_addr != -1 &&
246 back_buffer.render_addr != render_addr ) {
247 /* There's a current back buffer, and we're rendering somewhere else -
248 * flush the back buffer back to vram and start a new back buffer
249 */
250 pvr2_render_copy_to_sh4( &back_buffer, TRUE );
251 }
253 if( front_buffer.render_addr == render_addr ) {
254 /* In case we've been asked to render to the current front buffer -
255 * invalidate the front buffer and render to the back buffer, ensuring
256 * we swap at the next frame display.
257 */
258 front_buffer.render_addr = -1;
259 }
260 back_buffer.render_addr = render_addr;
261 back_buffer.width = width;
262 back_buffer.height = height;
263 back_buffer.colour_format = colour_format;
264 back_buffer.size = width * height * colour_format_bytes[colour_format];
266 /* Setup the display model */
267 glDrawBuffer(GL_BACK);
268 glShadeModel(GL_SMOOTH);
269 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
270 glViewport( 0, 0, width, height );
271 glMatrixMode(GL_PROJECTION);
272 glLoadIdentity();
273 glOrtho( 0, width, height, 0, bgplanez, -10 );
274 glMatrixMode(GL_MODELVIEW);
275 glLoadIdentity();
276 glCullFace( GL_BACK );
278 /* Clear out the buffers */
279 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
280 glClearDepth(bgplanez);
281 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
282 }
284 static void pvr2_dump_display_list( uint32_t * display_list, uint32_t length )
285 {
286 uint32_t i;
287 gboolean vertex = FALSE;
288 for( i =0; i<length>>2; i++ ) {
289 if( (i % 8) == 0 ) {
290 if( i != 0 )
291 fprintf( stderr, "\n" );
292 fprintf( stderr, "%08X:", i*4 );
293 if( display_list[i] == 0xE0000000 ||
294 display_list[i] == 0xF0000000 )
295 vertex = TRUE;
296 else vertex = FALSE;
297 }
298 if( vertex && (i%8) > 0 && (i%8) < 4 )
299 fprintf( stderr, " %f", ((float *)display_list)[i] );
300 else
301 fprintf( stderr, " %08X", display_list[i] );
302 }
303 fprintf( stderr, "\n" );
304 }
306 static void pvr2_render_display_list( uint32_t *display_list, uint32_t length )
307 {
308 uint32_t *cmd_ptr = display_list;
309 int strip_length = 0, vertex_count = 0;
310 int colour_type;
311 gboolean textured = FALSE;
312 gboolean shaded = FALSE;
313 struct pvr2_poly *poly;
314 if( pvr2_render_trace ) {
315 fprintf( stderr, "-------- %d\n", pvr2_get_frame_count() );
316 pvr2_dump_display_list( display_list, length );
317 }
318 while( cmd_ptr < display_list+(length>>2) ) {
319 unsigned int cmd = *cmd_ptr >> 24;
320 switch( cmd ) {
321 case PVR2_CMD_POLY_OPAQUE:
322 case PVR2_CMD_POLY_TRANS:
323 case PVR2_CMD_POLY_PUNCHOUT:
324 poly = (struct pvr2_poly *)cmd_ptr;
325 if( poly->command & PVR2_POLY_TEXTURED ) {
326 uint32_t addr = PVR2_TEX_ADDR(poly->texture);
327 int width = POLY_TEX_WIDTH(poly);
328 int height = POLY_TEX_HEIGHT(poly);
329 glEnable( GL_TEXTURE_2D );
330 texcache_get_texture( addr, width, height, poly->texture );
331 textured = TRUE;
332 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, POLY_TEX_BLEND(poly) );
333 } else {
334 textured = FALSE;
335 glDisable( GL_TEXTURE_2D );
336 }
337 glBlendFunc( POLY_BLEND_SRC(poly), POLY_BLEND_DEST(poly) );
338 if( poly->command & PVR2_POLY_SPECULAR ) {
339 /* Second block expected */
340 }
341 if( POLY_DEPTH_WRITE(poly) ) {
342 glEnable( GL_DEPTH_TEST );
343 glDepthFunc( POLY_DEPTH_MODE(poly) );
344 } else {
345 glDisable( GL_DEPTH_TEST );
346 }
348 switch( (poly->poly_cfg >> 27) & 0x03 ) {
349 case 0:
350 case 1:
351 glDisable( GL_CULL_FACE );
352 break;
353 case 2:
354 glEnable( GL_CULL_FACE );
355 glFrontFace( GL_CW );
356 break;
357 case 3:
358 glEnable( GL_CULL_FACE );
359 glFrontFace( GL_CCW );
360 }
361 strip_length = POLY_STRIP_VERTEXES( poly );
362 colour_type = POLY_COLOUR_TYPE( poly );
363 vertex_count = 0;
364 if( poly->command & PVR2_POLY_SHADED ) {
365 shaded = TRUE;
366 } else {
367 shaded = FALSE;
368 }
369 if( poly->poly_mode & PVR2_POLY_MODE_TEXALPHA ) {
370 glDisable( GL_BLEND );
371 } else {
372 glEnable( GL_BLEND );
373 }
375 break;
376 case PVR2_CMD_MOD_OPAQUE:
377 case PVR2_CMD_MOD_TRANS:
378 /* TODO */
379 break;
380 case PVR2_CMD_END_OF_LIST:
381 break;
382 case PVR2_CMD_VERTEX_LAST:
383 case PVR2_CMD_VERTEX:
384 if( vertex_count == 0 ) {
385 glBegin( GL_TRIANGLE_STRIP );
386 }
387 vertex_count++;
389 struct pvr2_vertex_packed *vertex = (struct pvr2_vertex_packed *)cmd_ptr;
390 if( textured ) {
391 glTexCoord2f( vertex->s, vertex->t );
393 if( shaded || vertex_count == 1) {
394 switch( colour_type ) {
395 case POLY_COLOUR_PACKED:
396 glColor4ub( vertex->colour >> 16, vertex->colour >> 8,
397 vertex->colour, vertex->colour >> 24 );
398 break;
399 }
400 }
401 } else {
402 if( shaded || vertex_count == 1 ) {
403 switch( colour_type ) {
404 case POLY_COLOUR_PACKED:
405 glColor4ub( vertex->colour >> 16, vertex->colour >> 8,
406 vertex->colour, vertex->colour >> 24 );
407 break;
408 case POLY_COLOUR_FLOAT:
409 {
410 struct pvr2_vertex_float *v = (struct pvr2_vertex_float *)cmd_ptr;
411 glColor4f( v->r, v->g, v->b, v->a );
412 }
413 break;
414 }
415 }
416 }
418 glVertex3f( vertex->x, vertex->y, vertex->z );
420 if( cmd == PVR2_CMD_VERTEX_LAST ) {
421 glEnd();
422 vertex_count = 0;
423 }
424 break;
425 default:
426 ERROR( "Unhandled command %08X in display list", *cmd_ptr );
427 pvr2_dump_display_list( display_list, length );
428 return;
429 }
430 cmd_ptr += 8; /* Next record */
431 }
432 }
434 #define MIN3( a,b,c ) ((a) < (b) ? ( (a) < (c) ? (a) : (c) ) : ((b) < (c) ? (b) : (c)) )
435 #define MAX3( a,b,c ) ((a) > (b) ? ( (a) > (c) ? (a) : (c) ) : ((b) > (c) ? (b) : (c)) )
437 /**
438 * Render the background plane as best we can. Unfortunately information
439 * is a little scant, to say the least.
440 */
441 void pvr2_render_draw_backplane( uint32_t mode, uint32_t *poly )
442 {
443 if( (mode >> 24) == 0x01 ) {
444 /* Packed colour. I think */
445 pvr2_bgplane_packed_t bg = (pvr2_bgplane_packed_t)poly;
446 if( bg->colour1 != bg->colour2 || bg->colour2 != bg->colour3 ) {
447 WARN( "Multiple background colours specified. Confused" );
448 }
449 float x1 = MIN3( bg->x1, bg->x2, bg->x3 );
450 float y1 = MIN3( bg->y1, bg->y2, bg->y3 );
451 float x2 = MAX3( bg->x1, bg->x2, bg->x3 );
452 float y2 = MAX3( bg->y1, bg->y2, bg->y3 );
453 float z = MIN3( bg->z1, bg->z2, bg->z3 );
454 glDisable( GL_TEXTURE_2D );
455 glDisable( GL_DEPTH_TEST );
456 glColor3ub( (uint8_t)(bg->colour1 >> 16), (uint8_t)(bg->colour1 >> 8),
457 (uint8_t)bg->colour1 );
458 glBegin( GL_QUADS );
459 glVertex3f( x1, y1, z );
460 glVertex3f( x2, y1, z );
461 glVertex3f( x2, y2, z );
462 glVertex3f( x1, y2, z );
463 glEnd();
464 } else {
465 WARN( "Unknown bgplane mode: %08X", mode );
466 fwrite_dump( poly, 48, stderr );
467 }
468 }
470 /**
471 * Render a complete scene into the OpenGL back buffer.
472 * Note: this will probably need to be broken up eventually once timings are
473 * determined.
474 */
475 void pvr2_render_scene( )
476 {
477 struct tile_descriptor *tile_desc =
478 (struct tile_descriptor *)mem_get_region(PVR2_RAM_BASE + MMIO_READ( PVR2, TILEBASE ));
480 uint32_t render_addr = MMIO_READ( PVR2, RENDADDR1 );
481 gboolean render_to_tex;
482 if( render_addr & 0x01000000 ) {
483 render_addr = (render_addr & 0x00FFFFFF) + PVR2_RAM_BASE_INT;
484 /* Heuristic - if we're rendering to the interlaced region we're
485 * probably creating a texture rather than rendering actual output.
486 * We can optimise for this case a little
487 */
488 render_to_tex = TRUE;
489 WARN( "Render to texture not supported properly yet" );
490 } else {
491 render_addr = (render_addr & 0x00FFFFFF) + PVR2_RAM_BASE;
492 render_to_tex = FALSE;
493 }
495 float bgplanez = MMIO_READF( PVR2, BGPLANEZ );
496 uint32_t render_mode = MMIO_READ( PVR2, RENDMODE );
497 int width = 640; /* FIXME - get this from the tile buffer */
498 int height = 480;
499 int colour_format = pvr2_render_colour_format[render_mode&0x07];
500 pvr2_render_prepare_context( render_addr, width, height, colour_format,
501 bgplanez, render_to_tex );
503 uint32_t *display_list =
504 (uint32_t *)mem_get_region(PVR2_RAM_BASE + MMIO_READ( PVR2, OBJBASE ));
506 uint32_t display_length = *display_list++;
508 int clip_x = MMIO_READ( PVR2, HCLIP ) & 0x03FF;
509 int clip_y = MMIO_READ( PVR2, VCLIP ) & 0x03FF;
510 int clip_width = ((MMIO_READ( PVR2, HCLIP ) >> 16) & 0x03FF) - clip_x + 1;
511 int clip_height= ((MMIO_READ( PVR2, VCLIP ) >> 16) & 0x03FF) - clip_y + 1;
513 if( clip_x == 0 && clip_y == 0 && clip_width == width && clip_height == height ) {
514 glDisable( GL_SCISSOR_TEST );
515 } else {
516 glEnable( GL_SCISSOR_TEST );
517 glScissor( clip_x, clip_y, clip_width, clip_height );
518 }
520 /* Fog setup goes here */
522 /* Render the background plane */
523 uint32_t bgplane_mode = MMIO_READ(PVR2, BGPLANE);
524 uint32_t *bgplane = display_list + (((bgplane_mode & 0x00FFFFFF)) >> 3) - 1;
525 pvr2_render_draw_backplane( bgplane_mode, bgplane );
527 /* Render the display list */
528 pvr2_render_display_list( display_list, display_length );
530 /* Post-render cleanup and update */
532 /* Add frame, fps, etc data */
533 glPrintf( 4, 16, "Frame %d", pvr2_get_frame_count() );
535 /* Generate end of render event */
536 asic_event( EVENT_PVR_RENDER_DONE );
537 DEBUG( "Rendered frame %d", pvr2_get_frame_count() );
538 }
541 /**
542 * Flush the indicated render buffer back to PVR. Caller is responsible for
543 * tracking whether there is actually anything in the buffer.
544 *
545 * @param buffer A render buffer indicating the address to store to, and the
546 * format the data needs to be in.
547 * @param backBuffer TRUE to flush the back buffer, FALSE for
548 * the front buffer.
549 */
550 void pvr2_render_copy_to_sh4( pvr2_render_buffer_t buffer,
551 gboolean backBuffer )
552 {
553 if( buffer->render_addr == -1 )
554 return;
555 GLenum type, format = GL_RGBA;
556 int size = buffer->width * buffer->height;
558 switch( buffer->colour_format ) {
559 case COLFMT_RGB565:
560 type = GL_UNSIGNED_SHORT_5_6_5;
561 format = GL_RGB;
562 size <<= 1;
563 break;
564 case COLFMT_RGB888:
565 type = GL_UNSIGNED_INT;
566 format = GL_RGB;
567 size = (size<<1)+size;
568 break;
569 case COLFMT_ARGB1555:
570 type = GL_UNSIGNED_SHORT_5_5_5_1;
571 size <<= 1;
572 break;
573 case COLFMT_ARGB4444:
574 type = GL_UNSIGNED_SHORT_4_4_4_4;
575 size <<= 1;
576 break;
577 case COLFMT_ARGB8888:
578 type = GL_UNSIGNED_INT_8_8_8_8;
579 size <<= 2;
580 break;
581 }
583 if( backBuffer ) {
584 glFinish();
585 glReadBuffer( GL_BACK );
586 } else {
587 glReadBuffer( GL_FRONT );
588 }
590 if( buffer->render_addr & 0xFF000000 == 0x04000000 ) {
591 /* Interlaced buffer. Go the double copy... :( */
592 char target[size];
593 glReadPixels( 0, 0, buffer->width, buffer->height, format, type, target );
594 pvr2_vram64_write( buffer->render_addr, target, size );
595 } else {
596 /* Regular buffer - go direct */
597 char *target = mem_get_region( buffer->render_addr );
598 glReadPixels( 0, 0, buffer->width, buffer->height, format, type, target );
599 }
600 }
603 /**
604 * Copy data from PVR ram into the GL render buffer.
605 *
606 * @param buffer A render buffer indicating the address to read from, and the
607 * format the data is in.
608 * @param backBuffer TRUE to write the back buffer, FALSE for
609 * the front buffer.
610 */
611 void pvr2_render_copy_from_sh4( pvr2_render_buffer_t buffer,
612 gboolean backBuffer )
613 {
614 if( buffer->render_addr == -1 )
615 return;
616 GLenum type, format = GL_RGBA;
617 int size = buffer->width * buffer->height;
619 switch( buffer->colour_format ) {
620 case COLFMT_RGB565:
621 type = GL_UNSIGNED_SHORT_5_6_5;
622 format = GL_RGB;
623 size <<= 1;
624 break;
625 case COLFMT_RGB888:
626 type = GL_UNSIGNED_INT;
627 format = GL_RGB;
628 size = (size<<1)+size;
629 break;
630 case COLFMT_ARGB1555:
631 type = GL_UNSIGNED_SHORT_5_5_5_1;
632 size <<= 1;
633 break;
634 case COLFMT_ARGB4444:
635 type = GL_UNSIGNED_SHORT_4_4_4_4;
636 size <<= 1;
637 break;
638 case COLFMT_ARGB8888:
639 type = GL_UNSIGNED_INT_8_8_8_8;
640 size <<= 2;
641 break;
642 }
644 if( backBuffer ) {
645 glDrawBuffer( GL_BACK );
646 } else {
647 glDrawBuffer( GL_FRONT );
648 }
650 glRasterPos2i( 0, 0 );
651 if( buffer->render_addr & 0xFF000000 == 0x04000000 ) {
652 /* Interlaced buffer. Go the double copy... :( */
653 char target[size];
654 pvr2_vram64_read( target, buffer->render_addr, size );
655 glDrawPixels( buffer->width, buffer->height,
656 format, type, target );
657 } else {
658 /* Regular buffer - go direct */
659 char *target = mem_get_region( buffer->render_addr );
660 glDrawPixels( buffer->width, buffer->height,
661 format, type, target );
662 }
663 }
.