4 * Manage the internal vertex/polygon buffers and scene data structure.
5 * Where possible this uses VBOs for the vertex + index data.
7 * Copyright (c) 2005 Nathan Keynes.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
25 #include "pvr2/pvr2.h"
26 #include "pvr2/pvr2mmio.h"
27 #include "pvr2/glutil.h"
28 #include "pvr2/scene.h"
30 static void unpack_bgra(uint32_t bgra, float *rgba)
32 rgba[0] = ((float)(((bgra&0x00FF0000)>>16) + 1)) / 256.0;
33 rgba[1] = ((float)(((bgra&0x0000FF00)>>8) + 1)) / 256.0;
34 rgba[2] = ((float)((bgra&0x000000FF) + 1)) / 256.0;
35 rgba[3] = ((float)(((bgra&0xFF000000)>>24) + 1)) / 256.0;
38 static inline uint32_t bgra_to_rgba(uint32_t bgra)
40 return (bgra&0xFF00FF00) | ((bgra&0x00FF0000)>>16) | ((bgra&0x000000FF)<<16);
44 * Convert a half-float (16-bit) FP number to a regular 32-bit float.
45 * Source is 1-bit sign, 5-bit exponent, 10-bit mantissa.
46 * TODO: Check the correctness of this.
48 static float halftofloat( uint16_t half )
54 temp.i = ((uint32_t)half)<<16;
58 static float parse_fog_density( uint32_t value )
64 u.i = (((value+127)&0xFF)<<23)|((value & 0xFF00)<<7);
69 struct pvr2_scene_struct pvr2_scene;
71 static gboolean vbo_init = FALSE;
73 #ifdef ENABLE_VERTEX_BUFFER
74 static gboolean vbo_supported = FALSE;
78 * Test for VBO support, and allocate all the system memory needed for the
79 * temporary structures. GL context must have been initialized before this
82 void pvr2_scene_init()
85 #ifdef ENABLE_VERTEX_BUFFER
86 if( isGLVertexBufferSupported() ) {
88 pvr2_scene.vbo_id = 1;
91 pvr2_scene.vertex_array = NULL;
92 pvr2_scene.vertex_array_size = 0;
93 pvr2_scene.poly_array = g_malloc( MAX_POLY_BUFFER_SIZE );
94 pvr2_scene.buf_to_poly_map = g_malloc0( BUF_POLY_MAP_SIZE );
100 * Clear the scene data structures in preparation for fresh data
102 void pvr2_scene_reset()
104 pvr2_scene.poly_count = 0;
105 pvr2_scene.vertex_count = 0;
106 memset( pvr2_scene.buf_to_poly_map, 0, BUF_POLY_MAP_SIZE );
109 void pvr2_scene_shutdown()
111 #ifdef ENABLE_VERTEX_BUFFER
112 if( vbo_supported ) {
113 glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
114 glDeleteBuffersARB( 1, &pvr2_scene.vbo_id );
115 pvr2_scene.vbo_id = 0;
118 g_free( pvr2_scene.vertex_array );
119 pvr2_scene.vertex_array = NULL;
120 #ifdef ENABLE_VERTEX_BUFFER
124 g_free( pvr2_scene.poly_array );
125 pvr2_scene.poly_array = NULL;
126 g_free( pvr2_scene.buf_to_poly_map );
127 pvr2_scene.buf_to_poly_map = NULL;
131 void *vertex_buffer_map()
133 // Allow 8 vertexes for the background (4+4)
134 uint32_t size = (pvr2_scene.vertex_count + 8) * sizeof(struct vertex_struct);
135 #ifdef ENABLE_VERTEX_BUFFER
136 if( vbo_supported ) {
138 glBindBufferARB( GL_ARRAY_BUFFER_ARB, pvr2_scene.vbo_id );
139 if( size > pvr2_scene.vertex_array_size ) {
140 glBufferDataARB( GL_ARRAY_BUFFER_ARB, size, NULL, GL_DYNAMIC_DRAW_ARB );
141 int status = glGetError();
143 fprintf( stderr, "Error %08X allocating vertex buffer\n", status );
146 pvr2_scene.vertex_array_size = size;
148 pvr2_scene.vertex_array = glMapBufferARB( GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB );
149 assert(pvr2_scene.vertex_array != NULL );
152 if( size > pvr2_scene.vertex_array_size ) {
153 pvr2_scene.vertex_array = g_realloc( pvr2_scene.vertex_array, size );
155 #ifdef ENABLE_VERTEX_BUFFER
158 return pvr2_scene.vertex_array;
161 gboolean vertex_buffer_unmap()
163 #ifdef ENABLE_VERTEX_BUFFER
164 if( vbo_supported ) {
165 pvr2_scene.vertex_array = NULL;
166 return glUnmapBufferARB( GL_ARRAY_BUFFER_ARB );
175 static struct polygon_struct *scene_add_polygon( pvraddr_t poly_idx, int vertex_count,
176 gboolean is_modified )
178 int vert_mul = is_modified ? 2 : 1;
180 if( pvr2_scene.buf_to_poly_map[poly_idx] != NULL ) {
181 if( vertex_count > pvr2_scene.buf_to_poly_map[poly_idx]->vertex_count ) {
182 pvr2_scene.vertex_count += (vertex_count - pvr2_scene.buf_to_poly_map[poly_idx]->vertex_count) * vert_mul;
183 pvr2_scene.buf_to_poly_map[poly_idx]->vertex_count = vertex_count;
185 return pvr2_scene.buf_to_poly_map[poly_idx];
187 struct polygon_struct *poly = &pvr2_scene.poly_array[pvr2_scene.poly_count++];
188 poly->context = &pvr2_scene.pvr2_pbuf[poly_idx];
189 poly->vertex_count = vertex_count;
190 poly->vertex_index = -1;
191 poly->mod_vertex_index = -1;
193 pvr2_scene.buf_to_poly_map[poly_idx] = poly;
194 pvr2_scene.vertex_count += (vertex_count * vert_mul);
200 * Decode a single PVR2 renderable vertex (opaque/trans/punch-out, but not shadow
202 * @param vert Pointer to output vertex structure
203 * @param poly1 First word of polygon context (needed to understand vertex)
204 * @param poly2 Second word of polygon context
205 * @param pvr2_data Pointer to raw pvr2 vertex data (in VRAM)
206 * @param modify_offset Offset in 32-bit words to the tex/color data. 0 for
207 * the normal vertex, half the vertex length for the modified vertex.
209 static void pvr2_decode_render_vertex( struct vertex_struct *vert, uint32_t poly1,
210 uint32_t poly2, uint32_t *pvr2_data,
213 gboolean force_alpha = !POLY2_ALPHA_ENABLE(poly2);
214 union pvr2_data_type {
219 data.ival = pvr2_data;
221 vert->x = *data.fval++;
222 vert->y = *data.fval++;
224 float z = *data.fval++;
227 } else if( z != 0 ) {
230 if( z > pvr2_scene.bounds[5] ) {
231 pvr2_scene.bounds[5] = z;
232 } else if( z < pvr2_scene.bounds[4] && z != 0 ) {
233 pvr2_scene.bounds[4] = z;
236 data.ival += modify_offset;
239 if( POLY1_TEXTURED(poly1) ) {
240 if( POLY1_UV16(poly1) ) {
241 vert->u = halftofloat( *data.ival>>16 );
242 vert->v = halftofloat( *data.ival );
245 vert->u = *data.fval++;
246 vert->v = *data.fval++;
248 if( POLY2_TEX_BLEND(poly2) == 1 ) {
252 unpack_bgra(*data.ival++, vert->rgba);
253 if( POLY1_SPECULAR(poly1) ) {
254 unpack_bgra(*data.ival++, vert->offset_rgba);
256 vert->offset_rgba[0] = 0.0;
257 vert->offset_rgba[1] = 0.0;
258 vert->offset_rgba[2] = 0.0;
259 vert->offset_rgba[3] = 0.0;
268 * Compute texture, colour, and z values for 1 or more result points by interpolating from
269 * a set of 3 input points. The result point(s) must define their x,y.
271 static void scene_compute_vertexes( struct vertex_struct *result,
273 struct vertex_struct *input,
274 gboolean is_solid_shaded )
277 float sx = input[2].x - input[1].x;
278 float sy = input[2].y - input[1].y;
279 float tx = input[0].x - input[1].x;
280 float ty = input[0].y - input[1].y;
282 float detxy = ((sy) * (tx)) - ((ty) * (sx));
284 // If the input points fall on a line, they don't define a usable
285 // polygon - the PVR2 takes the last input point as the result in
287 for( i=0; i<result_count; i++ ) {
288 float x = result[i].x;
289 float y = result[i].y;
290 memcpy( &result[i], &input[2], sizeof(struct vertex_struct) );
296 float sz = input[2].z - input[1].z;
297 float tz = input[0].z - input[1].z;
298 float su = input[2].u - input[1].u;
299 float tu = input[0].u - input[1].u;
300 float sv = input[2].v - input[1].v;
301 float tv = input[0].v - input[1].v;
303 for( i=0; i<result_count; i++ ) {
304 float t = ((result[i].x - input[1].x) * sy -
305 (result[i].y - input[1].y) * sx) / detxy;
306 float s = ((result[i].y - input[1].y) * tx -
307 (result[i].x - input[1].x) * ty) / detxy;
309 float rz = input[1].z + (t*tz) + (s*sz);
310 if( rz > pvr2_scene.bounds[5] ) {
311 pvr2_scene.bounds[5] = rz;
312 } else if( rz < pvr2_scene.bounds[4] ) {
313 pvr2_scene.bounds[4] = rz;
316 result[i].u = input[1].u + (t*tu) + (s*su);
317 result[i].v = input[1].v + (t*tv) + (s*sv);
319 if( is_solid_shaded ) {
320 memcpy( result->rgba, input[2].rgba, sizeof(result->rgba) );
321 memcpy( result->offset_rgba, input[2].offset_rgba, sizeof(result->offset_rgba) );
323 float *rgba0 = input[0].rgba;
324 float *rgba1 = input[1].rgba;
325 float *rgba2 = input[2].rgba;
326 float *rgba3 = result[i].rgba;
327 for( j=0; j<8; j++ ) {
328 float tc = *rgba0++ - *rgba1;
329 float sc = *rgba2++ - *rgba1;
330 float rc = *rgba1++ + (t*tc) + (s*sc);
337 static float scene_compute_lut_fog_vertex( float z, float fog_density, float fog_table[][2] )
343 v.f = z * fog_density;
344 if( v.f < 1.0 ) v.f = 1.0;
345 else if( v.f > 255.9999 ) v.f = 255.9999;
347 uint32_t index = ((v.i >> 18) & 0x0F)|((v.i>>19)&0x70);
348 return fog_table[index][0];
352 * Compute the fog coefficients for all polygons using lookup-table fog. It's
353 * a little more convenient to do this as a separate pass, since we don't have
354 * to worry about computed vertexes.
356 static void scene_compute_lut_fog( )
360 float fog_density = parse_fog_density(MMIO_READ( PVR2, RENDER_FOGCOEFF ));
361 float fog_table[128][2];
363 /* Parse fog table out into floating-point format */
364 for( i=0; i<128; i++ ) {
365 uint32_t ent = MMIO_READ( PVR2, RENDER_FOGTABLE + (i<<2) );
366 fog_table[i][0] = ((float)(((ent&0x0000FF00)>>8) + 1)) / 256.0;
367 fog_table[i][1] = ((float)((ent&0x000000FF) + 1)) / 256.0;
371 for( i=0; i<pvr2_scene.poly_count; i++ ) {
372 int mode = POLY2_FOG_MODE(pvr2_scene.poly_array[i].context[1]);
373 if( mode == PVR2_POLY_FOG_LOOKUP ) {
374 uint32_t index = pvr2_scene.poly_array[i].vertex_index;
375 for( j=0; j<=pvr2_scene.poly_array[i].vertex_count; j++ ) {
376 pvr2_scene.vertex_array[index+j].offset_rgba[3] =
377 scene_compute_lut_fog_vertex( pvr2_scene.vertex_array[index+j].z, fog_density, fog_table );
379 } else if( mode == PVR2_POLY_FOG_LOOKUP2 ) {
380 uint32_t index = pvr2_scene.poly_array[i].vertex_index;
381 for( j=0; j<=pvr2_scene.poly_array[i].vertex_count; j++ ) {
382 pvr2_scene.vertex_array[index+j].rgba[0] = pvr2_scene.fog_lut_colour[0];
383 pvr2_scene.vertex_array[index+j].rgba[1] = pvr2_scene.fog_lut_colour[1];
384 pvr2_scene.vertex_array[index+j].rgba[2] = pvr2_scene.fog_lut_colour[2];
385 pvr2_scene.vertex_array[index+j].rgba[3] =
386 scene_compute_lut_fog_vertex( pvr2_scene.vertex_array[index+j].z, fog_density, fog_table );
392 static void scene_add_vertexes( pvraddr_t poly_idx, int vertex_length,
393 gboolean is_modified )
395 struct polygon_struct *poly = pvr2_scene.buf_to_poly_map[poly_idx];
396 uint32_t *ptr = &pvr2_scene.pvr2_pbuf[poly_idx];
397 uint32_t *context = ptr;
400 if( poly->vertex_index == -1 ) {
401 ptr += (is_modified ? 5 : 3 );
402 poly->vertex_index = pvr2_scene.vertex_index;
404 assert( poly != NULL );
405 assert( pvr2_scene.vertex_index + poly->vertex_count <= pvr2_scene.vertex_count );
406 for( i=0; i<poly->vertex_count; i++ ) {
407 pvr2_decode_render_vertex( &pvr2_scene.vertex_array[pvr2_scene.vertex_index++], context[0], context[1], ptr, 0 );
408 ptr += vertex_length;
411 int mod_offset = (vertex_length - 3)>>1;
412 assert( pvr2_scene.vertex_index + poly->vertex_count <= pvr2_scene.vertex_count );
413 ptr = &pvr2_scene.pvr2_pbuf[poly_idx] + 5;
414 poly->mod_vertex_index = pvr2_scene.vertex_index;
415 for( i=0; i<poly->vertex_count; i++ ) {
416 pvr2_decode_render_vertex( &pvr2_scene.vertex_array[pvr2_scene.vertex_index++], context[0], context[3], ptr, mod_offset );
417 ptr += vertex_length;
423 static void scene_add_quad_vertexes( pvraddr_t poly_idx, int vertex_length,
424 gboolean is_modified )
426 struct polygon_struct *poly = pvr2_scene.buf_to_poly_map[poly_idx];
427 uint32_t *ptr = &pvr2_scene.pvr2_pbuf[poly_idx];
428 uint32_t *context = ptr;
431 if( poly->vertex_index == -1 ) {
432 // Construct it locally and copy to the vertex buffer, as the VBO is
433 // allowed to be horribly slow for reads (ie it could be direct-mapped
435 struct vertex_struct quad[4];
437 assert( poly != NULL );
438 assert( pvr2_scene.vertex_index + poly->vertex_count <= pvr2_scene.vertex_count );
439 ptr += (is_modified ? 5 : 3 );
440 poly->vertex_index = pvr2_scene.vertex_index;
441 for( i=0; i<4; i++ ) {
442 pvr2_decode_render_vertex( &quad[i], context[0], context[1], ptr, 0 );
443 ptr += vertex_length;
445 scene_compute_vertexes( &quad[3], 1, &quad[0], !POLY1_GOURAUD_SHADED(context[0]) );
446 // Swap last two vertexes (quad arrangement => tri strip arrangement)
447 memcpy( &pvr2_scene.vertex_array[pvr2_scene.vertex_index], quad, sizeof(struct vertex_struct)*2 );
448 memcpy( &pvr2_scene.vertex_array[pvr2_scene.vertex_index+2], &quad[3], sizeof(struct vertex_struct) );
449 memcpy( &pvr2_scene.vertex_array[pvr2_scene.vertex_index+3], &quad[2], sizeof(struct vertex_struct) );
450 pvr2_scene.vertex_index += 4;
453 int mod_offset = (vertex_length - 3)>>1;
454 assert( pvr2_scene.vertex_index + poly->vertex_count <= pvr2_scene.vertex_count );
455 ptr = &pvr2_scene.pvr2_pbuf[poly_idx] + 5;
456 poly->mod_vertex_index = pvr2_scene.vertex_index;
457 for( i=0; i<4; i++ ) {
458 pvr2_decode_render_vertex( &quad[4], context[0], context[3], ptr, mod_offset );
459 ptr += vertex_length;
461 scene_compute_vertexes( &quad[3], 1, &quad[0], !POLY1_GOURAUD_SHADED(context[0]) );
462 memcpy( &pvr2_scene.vertex_array[pvr2_scene.vertex_index], quad, sizeof(struct vertex_struct)*2 );
463 memcpy( &pvr2_scene.vertex_array[pvr2_scene.vertex_index+2], &quad[3], sizeof(struct vertex_struct) );
464 memcpy( &pvr2_scene.vertex_array[pvr2_scene.vertex_index+3], &quad[2], sizeof(struct vertex_struct) );
465 pvr2_scene.vertex_index += 4;
470 static void scene_extract_polygons( pvraddr_t tile_entry )
472 uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);
474 uint32_t entry = *tile_list++;
475 if( entry >> 28 == 0x0F ) {
477 } else if( entry >> 28 == 0x0E ) {
478 tile_list = (uint32_t *)(video_base + (entry&0x007FFFFF));
480 pvraddr_t polyaddr = entry&0x000FFFFF;
481 int is_modified = (entry & 0x01000000) && pvr2_scene.full_shadow;
482 int vertex_length = (entry >> 21) & 0x07;
483 int context_length = 3;
486 vertex_length <<= 1 ;
490 if( (entry & 0xE0000000) == 0x80000000 ) {
492 int strip_count = ((entry >> 25) & 0x0F)+1;
493 int polygon_length = 3 * vertex_length + context_length;
495 struct polygon_struct *last_poly = NULL;
496 for( i=0; i<strip_count; i++ ) {
497 struct polygon_struct *poly = scene_add_polygon( polyaddr, 3, is_modified );
498 polyaddr += polygon_length;
499 if( last_poly != NULL && last_poly->next == NULL ) {
500 last_poly->next = poly;
504 } else if( (entry & 0xE0000000) == 0xA0000000 ) {
506 int strip_count = ((entry >> 25) & 0x0F)+1;
507 int polygon_length = 4 * vertex_length + context_length;
509 struct polygon_struct *last_poly = NULL;
510 for( i=0; i<strip_count; i++ ) {
511 struct polygon_struct *poly = scene_add_polygon( polyaddr, 4, is_modified );
512 polyaddr += polygon_length;
513 if( last_poly != NULL && last_poly->next == NULL ) {
514 last_poly->next = poly;
521 for( i=5; i>=0; i-- ) {
522 if( entry & (0x40000000>>i) ) {
528 scene_add_polygon( polyaddr, last+3, is_modified );
535 static void scene_extract_vertexes( pvraddr_t tile_entry )
537 uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);
539 uint32_t entry = *tile_list++;
540 if( entry >> 28 == 0x0F ) {
542 } else if( entry >> 28 == 0x0E ) {
543 tile_list = (uint32_t *)(video_base + (entry&0x007FFFFF));
545 pvraddr_t polyaddr = entry&0x000FFFFF;
546 int is_modified = (entry & 0x01000000) && pvr2_scene.full_shadow;
547 int vertex_length = (entry >> 21) & 0x07;
548 int context_length = 3;
555 if( (entry & 0xE0000000) == 0x80000000 ) {
557 int strip_count = ((entry >> 25) & 0x0F)+1;
558 int polygon_length = 3 * vertex_length + context_length;
560 for( i=0; i<strip_count; i++ ) {
561 scene_add_vertexes( polyaddr, vertex_length, is_modified );
562 polyaddr += polygon_length;
564 } else if( (entry & 0xE0000000) == 0xA0000000 ) {
566 int strip_count = ((entry >> 25) & 0x0F)+1;
567 int polygon_length = 4 * vertex_length + context_length;
569 for( i=0; i<strip_count; i++ ) {
570 scene_add_quad_vertexes( polyaddr, vertex_length, is_modified );
571 polyaddr += polygon_length;
576 for( i=5; i>=0; i-- ) {
577 if( entry & (0x40000000>>i) ) {
583 scene_add_vertexes( polyaddr, vertex_length, is_modified );
590 static void scene_extract_background( void )
592 uint32_t bgplane = MMIO_READ(PVR2, RENDER_BGPLANE);
593 int vertex_length = (bgplane >> 24) & 0x07;
594 int context_length = 3, i;
595 int is_modified = (bgplane & 0x08000000) && pvr2_scene.full_shadow;
597 struct polygon_struct *poly = &pvr2_scene.poly_array[pvr2_scene.poly_count++];
598 uint32_t *context = &pvr2_scene.pvr2_pbuf[(bgplane & 0x00FFFFFF)>>3];
599 poly->context = context;
600 poly->vertex_count = 4;
601 poly->vertex_index = pvr2_scene.vertex_count;
605 poly->mod_vertex_index = pvr2_scene.vertex_count + 4;
606 pvr2_scene.vertex_count += 8;
608 poly->mod_vertex_index = -1;
609 pvr2_scene.vertex_count += 4;
612 context_length += (bgplane & 0x07) * vertex_length;
615 pvr2_scene.bkgnd_poly = poly;
617 struct vertex_struct base_vertexes[3];
618 uint32_t *ptr = context + context_length;
619 for( i=0; i<3; i++ ) {
620 pvr2_decode_render_vertex( &base_vertexes[i], context[0], context[1],
622 ptr += vertex_length;
624 struct vertex_struct *result_vertexes = &pvr2_scene.vertex_array[poly->vertex_index];
625 result_vertexes[0].x = result_vertexes[0].y = 0;
626 result_vertexes[1].x = result_vertexes[3].x = pvr2_scene.buffer_width;
627 result_vertexes[1].y = result_vertexes[2].x = 0;
628 result_vertexes[2].y = result_vertexes[3].y = pvr2_scene.buffer_height;
629 scene_compute_vertexes( result_vertexes, 4, base_vertexes, !POLY1_GOURAUD_SHADED(context[0]) );
632 int mod_offset = (vertex_length - 3)>>1;
633 ptr = context + context_length;
634 for( i=0; i<3; i++ ) {
635 pvr2_decode_render_vertex( &base_vertexes[i], context[0], context[3],
637 ptr += vertex_length;
639 result_vertexes = &pvr2_scene.vertex_array[poly->mod_vertex_index];
640 result_vertexes[0].x = result_vertexes[0].y = 0;
641 result_vertexes[1].x = result_vertexes[3].x = pvr2_scene.buffer_width;
642 result_vertexes[1].y = result_vertexes[2].x = 0;
643 result_vertexes[2].y = result_vertexes[3].y = pvr2_scene.buffer_height;
644 scene_compute_vertexes( result_vertexes, 4, base_vertexes, !POLY1_GOURAUD_SHADED(context[0]) );
650 uint32_t pvr2_scene_buffer_width()
652 return pvr2_scene.buffer_width;
655 uint32_t pvr2_scene_buffer_height()
657 return pvr2_scene.buffer_height;
661 * Extract the current scene into the rendering structures. We run two passes
662 * - first pass extracts the polygons into pvr2_scene.poly_array (finding vertex counts),
663 * second pass extracts the vertex data into the VBO/vertex array.
665 * Difficult to do in single pass as we don't generally know the size of a
666 * polygon for certain until we've seen all tiles containing it. It also means we
667 * can count the vertexes and allocate the appropriate size VBO.
669 * FIXME: accesses into VRAM need to be bounds-checked properly
671 void pvr2_scene_read( void )
676 pvr2_scene.bounds[0] = MMIO_READ( PVR2, RENDER_HCLIP ) & 0x03FF;
677 pvr2_scene.bounds[1] = ((MMIO_READ( PVR2, RENDER_HCLIP ) >> 16) & 0x03FF) + 1;
678 pvr2_scene.bounds[2] = MMIO_READ( PVR2, RENDER_VCLIP ) & 0x03FF;
679 pvr2_scene.bounds[3] = ((MMIO_READ( PVR2, RENDER_VCLIP ) >> 16) & 0x03FF) + 1;
680 pvr2_scene.bounds[4] = pvr2_scene.bounds[5] = MMIO_READF( PVR2, RENDER_FARCLIP );
682 uint32_t scaler = MMIO_READ( PVR2, RENDER_SCALER );
683 if( scaler & SCALER_HSCALE ) {
684 /* If the horizontal scaler is in use, we're (in principle) supposed to
685 * divide everything by 2. However in the interests of display quality,
686 * instead we want to render to the unscaled resolution and downsample
687 * only if/when required.
689 pvr2_scene.bounds[1] *= 2;
692 uint32_t fog_col = MMIO_READ( PVR2, RENDER_FOGTBLCOL );
693 unpack_bgra( fog_col, pvr2_scene.fog_lut_colour );
694 fog_col = MMIO_READ( PVR2, RENDER_FOGVRTCOL );
695 unpack_bgra( fog_col, pvr2_scene.fog_vert_colour );
697 uint32_t *tilebuffer = (uint32_t *)(video_base + MMIO_READ( PVR2, RENDER_TILEBASE ));
698 uint32_t *segment = tilebuffer;
699 pvr2_scene.segment_list = (struct tile_segment *)tilebuffer;
700 pvr2_scene.pvr2_pbuf = (uint32_t *)(video_base + MMIO_READ(PVR2,RENDER_POLYBASE));
701 pvr2_scene.full_shadow = MMIO_READ( PVR2, RENDER_SHADOW ) & 0x100 ? FALSE : TRUE;
705 int obj_config = MMIO_READ( PVR2, RENDER_OBJCFG );
706 int isp_config = MMIO_READ( PVR2, RENDER_ISPCFG );
708 if( (obj_config & 0x00200000) == 0 ) {
709 if( isp_config & 1 ) {
710 pvr2_scene.sort_mode = SORT_NEVER;
712 pvr2_scene.sort_mode = SORT_ALWAYS;
715 pvr2_scene.sort_mode = SORT_TILEFLAG;
718 // Pass 1: Extract polygon list
722 control = *segment++;
723 int tile_x = SEGMENT_X(control);
724 int tile_y = SEGMENT_Y(control);
725 if( tile_x > max_tile_x ) {
728 if( tile_y > max_tile_y ) {
731 for( i=0; i<5; i++ ) {
732 if( (*segment & NO_POINTER) == 0 ) {
733 scene_extract_polygons( *segment );
737 } while( (control & SEGMENT_END) == 0 );
739 pvr2_scene.buffer_width = (max_tile_x+1)<<5;
740 pvr2_scene.buffer_height = (max_tile_y+1)<<5;
742 // Pass 2: Extract vertex data
744 pvr2_scene.vertex_index = 0;
745 segment = tilebuffer;
747 control = *segment++;
748 for( i=0; i<5; i++ ) {
749 if( (*segment & NO_POINTER) == 0 ) {
750 scene_extract_vertexes( *segment );
754 } while( (control & SEGMENT_END) == 0 );
756 scene_extract_background();
757 scene_compute_lut_fog();
759 vertex_buffer_unmap();
763 * Dump the current scene to file in a (mostly) human readable form
765 void pvr2_scene_dump( FILE *f )
769 fprintf( f, "Polygons: %d\n", pvr2_scene.poly_count );
770 for( i=0; i<pvr2_scene.poly_count; i++ ) {
771 struct polygon_struct *poly = &pvr2_scene.poly_array[i];
772 fprintf( f, " %08X ", ((unsigned char *)poly->context) - video_base );
773 switch( poly->vertex_count ) {
774 case 3: fprintf( f, "Tri " ); break;
775 case 4: fprintf( f, "Quad " ); break;
776 default: fprintf( f,"%d-Strip ", poly->vertex_count-2 ); break;
778 fprintf( f, "%08X %08X %08X ", poly->context[0], poly->context[1], poly->context[2] );
779 if( poly->mod_vertex_index != -1 ) {
780 fprintf( f, "%08X %08X\n", poly->context[3], poly->context[5] );
785 for( j=0; j<poly->vertex_count; j++ ) {
786 struct vertex_struct *v = &pvr2_scene.vertex_array[poly->vertex_index+j];
787 fprintf( f, " %.5f %.5f %.5f, (%.5f,%.5f) %.5f,%.5f,%.5f,%.5f %.5f %.5f %.5f %.5f\n", v->x, v->y, v->z, v->u, v->v,
788 v->rgba[0], v->rgba[1], v->rgba[2], v->rgba[3],
789 v->offset_rgba[0], v->offset_rgba[1], v->offset_rgba[2], v->offset_rgba[3] );
791 if( poly->mod_vertex_index != -1 ) {
792 fprintf( f, " ---\n" );
793 for( j=0; j<poly->vertex_count; j++ ) {
794 struct vertex_struct *v = &pvr2_scene.vertex_array[poly->mod_vertex_index+j];
795 fprintf( f, " %.5f %.5f %.5f, (%.5f,%.5f) %.5f,%.5f,%.5f,%.5f %.5f %.5f %.5f %.5f\n", v->x, v->y, v->z, v->u, v->v,
796 v->rgba[0], v->rgba[1], v->rgba[2], v->rgba[3],
797 v->offset_rgba[0], v->offset_rgba[1], v->offset_rgba[2], v->offset_rgba[3] );
.