Search
lxdream.org :: lxdream/src/pvr2/scene.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/scene.c
changeset 639:162ee7614b60
prev636:2ccf94f966fc
next645:a7392098299c
author nkeynes
date Mon Feb 18 09:21:43 2008 +0000 (12 years ago)
branchlxdream-render
permissions -rw-r--r--
last change More render WIP - initial glrender.c
view annotate diff log raw
     1 /**
     2  * $Id$
     3  *
     4  * Manage the internal vertex/polygon buffers and scene data structure. 
     5  * Where possible this uses VBOs for the vertex + index data.
     6  *
     7  * Copyright (c) 2005 Nathan Keynes.
     8  *
     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.
    13  *
    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.
    18  */
    20 #include <assert.h>
    21 #include <string.h>
    22 #include "lxdream.h"
    23 #include "display.h"
    24 #include "pvr2/pvr2.h"
    25 #include "pvr2/glutil.h"
    26 #include "pvr2/scene.h"
    28 #define VBO_EXT_STRING "GL_ARB_vertex_buffer_object"
    29 #define PBO_EXT_STRING "GL_ARB_pixel_buffer_object"
    31 static inline uint32_t bgra_to_rgba(uint32_t bgra)
    32 {
    33     return (bgra&0xFF00FF00) | ((bgra&0x00FF0000)>>16) | ((bgra&0x000000FF)<<16);
    34 }
    36 struct pvr2_scene_struct pvr2_scene;
    38 static gboolean vbo_init = FALSE;
    39 static gboolean vbo_supported = FALSE;
    41 /**
    42  * Test for VBO support, and allocate all the system memory needed for the
    43  * temporary structures. GL context must have been initialized before this
    44  * point.
    45  */
    46 void pvr2_scene_init()
    47 {
    48     if( !vbo_init ) {
    49 	if( isGLExtensionSupported(VBO_EXT_STRING) ) {
    50 	    vbo_supported = TRUE;
    51 	    pvr2_scene.vbo_id = 1;
    52 	}
    53 	pvr2_scene.vertex_array = NULL;
    54 	pvr2_scene.vertex_array_size = 0;
    55 	pvr2_scene.poly_array = g_malloc( MAX_POLY_BUFFER_SIZE );
    56 	pvr2_scene.buf_to_poly_map = g_malloc0( BUF_POLY_MAP_SIZE );
    57 	vbo_init = TRUE;
    58     }
    59 }
    61 /**
    62  * Clear the scene data structures in preparation for fresh data
    63  */
    64 void pvr2_scene_reset()
    65 {
    66     pvr2_scene.poly_count = 0;
    67     pvr2_scene.vertex_count = 0;
    68     memset( pvr2_scene.buf_to_poly_map, 0, BUF_POLY_MAP_SIZE );
    69 }
    71 void pvr2_scene_shutdown()
    72 {
    73     if( vbo_supported ) {
    74 	glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
    75 	glDeleteBuffersARB( 1, &pvr2_scene.vbo_id );
    76 	pvr2_scene.vbo_id = 0;
    77     } else {
    78 	g_free( pvr2_scene.vertex_array );
    79 	pvr2_scene.vertex_array = NULL;
    80     }
    81     g_free( pvr2_scene.poly_array );
    82     g_free( pvr2_scene.buf_to_poly_map );
    83     vbo_init = FALSE;
    84 }
    86 void *vertex_buffer_map()
    87 {
    88     glGetError();
    89     uint32_t size = pvr2_scene.vertex_count * sizeof(struct vertex_struct);
    90     if( vbo_supported ) {
    91 	glBindBufferARB( GL_ARRAY_BUFFER_ARB, pvr2_scene.vbo_id );
    92 	assert( glGetError() == 0 );
    93 	if( size > pvr2_scene.vertex_array_size ) {
    94 	    glBufferDataARB( GL_ARRAY_BUFFER_ARB, size, NULL, GL_DYNAMIC_DRAW_ARB );
    95 	    int status = glGetError();
    96 	    if( status != 0 ) {
    97 		fprintf( stderr, "Error %08X allocating vertex buffer\n", status );
    98 		abort();
    99 	    }
   100 	    pvr2_scene.vertex_array_size = size;
   101 	}
   102 	pvr2_scene.vertex_array = glMapBufferARB( GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB );
   103 	assert(pvr2_scene.vertex_array != NULL );
   104     } else {
   105 	if( size > pvr2_scene.vertex_array_size ) {
   106 	    pvr2_scene.vertex_array = g_realloc( pvr2_scene.vertex_array, size );
   107 	}
   108     }
   109     return pvr2_scene.vertex_array;
   110 }
   112 gboolean vertex_buffer_unmap()
   113 {
   114     if( vbo_supported ) {
   115 	pvr2_scene.vertex_array = NULL;
   116 	return glUnmapBufferARB( GL_ARRAY_BUFFER_ARB );
   117     } else {
   118 	return TRUE;
   119     }
   120 }
   122 static struct polygon_struct *scene_add_polygon( pvraddr_t poly_idx, int vertex_count,
   123 							 gboolean is_modified ) 
   124 {
   125     int vert_mul = is_modified ? 2 : 1;
   127     if( pvr2_scene.buf_to_poly_map[poly_idx] != NULL ) {
   128 	if( vertex_count > pvr2_scene.buf_to_poly_map[poly_idx]->vertex_count ) {
   129 	    pvr2_scene.vertex_count += (vertex_count - pvr2_scene.buf_to_poly_map[poly_idx]->vertex_count) * vert_mul;
   130 	    pvr2_scene.buf_to_poly_map[poly_idx]->vertex_count = vertex_count;
   131 	}
   132 	return pvr2_scene.buf_to_poly_map[poly_idx];
   133     } else {
   134 	struct polygon_struct *poly = &pvr2_scene.poly_array[pvr2_scene.poly_count++];
   135 	poly->context = (uint32_t *)(video_base + MMIO_READ(PVR2,RENDER_POLYBASE) + (poly_idx<<2));
   136 	poly->vertex_count = vertex_count;
   137 	poly->vertex_index = -1;
   138 	poly->next = NULL;
   139 	pvr2_scene.buf_to_poly_map[poly_idx] = poly;
   140 	pvr2_scene.vertex_count += (vertex_count * vert_mul);
   141 	return poly;
   142     }
   143 }
   145 /**
   146  * Decode a single PVR2 renderable vertex (opaque/trans/punch-out, but not shadow
   147  * volume)
   148  * @param vert Pointer to output vertex structure
   149  * @param poly1 First word of polygon context (needed to understand vertex)
   150  * @param poly2 Second word of polygon context
   151  * @param pvr2_data Pointer to raw pvr2 vertex data (in VRAM)
   152  * @param modify_offset Offset in 32-bit words to the tex/color data. 0 for
   153  *        the normal vertex, half the vertex length for the modified vertex.
   154  */
   155 static void pvr2_decode_render_vertex( struct vertex_struct *vert, uint32_t poly1, 
   156 				       uint32_t poly2, uint32_t *pvr2_data, 
   157 				       int modify_offset )
   158 {
   159     gboolean force_alpha = !POLY2_ALPHA_ENABLE(poly2);
   160     union pvr2_data_type {
   161 	uint32_t *ival;
   162 	float *fval;
   163     } data;
   165     data.ival = pvr2_data;
   167     vert->x = *data.fval++;
   168     vert->y = *data.fval++;
   170     float z = *data.fval++;
   171     if( z > pvr2_scene.bounds[5] ) {
   172 	pvr2_scene.bounds[5] = z;
   173     } else if( z < pvr2_scene.bounds[4] && z != 0 ) {
   174 	pvr2_scene.bounds[4] = z;
   175     }
   176     vert->z = z;
   177     data.ival += modify_offset;
   180     if( POLY1_TEXTURED(poly1) ) {
   181 	if( POLY1_UV16(poly1) ) {
   182 	    vert->u = halftofloat( *data.ival>>16 );
   183 	    vert->v = halftofloat( *data.ival );
   184 	    data.ival++;
   185 	} else {
   186 	    vert->u = *data.fval++;
   187 	    vert->v = *data.fval++;
   188 	}
   189 	if( POLY2_TEX_BLEND(poly2) == 1 ) {
   190 	    force_alpha = TRUE;
   191 	}
   192     }
   193     if( force_alpha ) {
   194 	vert->rgba = bgra_to_rgba((*data.ival++) | 0xFF000000);
   195 	if( POLY1_SPECULAR(poly1) ) {
   196 	    vert->offset_rgba = bgra_to_rgba((*data.ival++) | 0xFF000000);
   197 	}
   198     } else {
   199 	vert->rgba = bgra_to_rgba(*data.ival++);
   200 	if( POLY1_SPECULAR(poly1) ) {
   201 	    vert->offset_rgba = bgra_to_rgba(*data.ival++);
   202 	}
   203     }
   204 }
   206 /**
   207  * Compute texture, colour, and z values for a result point by interpolating from
   208  * a set of 3 input points. The result point must define its x,y.
   209  */
   210 static void scene_compute_vertex( struct vertex_struct *result, 
   211 					  struct vertex_struct *input,
   212 					  gboolean is_solid_shaded )
   213 {
   214     int i;
   215     float sx = input[2].x - input[1].x;
   216     float sy = input[2].y - input[1].y;
   217     float tx = input[0].x - input[1].x;
   218     float ty = input[0].y - input[1].y;
   220     float detxy = ((sy) * (tx)) - ((ty) * (sx));
   221     if( detxy == 0 ) {
   222 	result->z = input[2].z;
   223 	result->u = input[2].u;
   224 	result->v = input[2].v;
   225 	result->rgba = input[2].rgba;
   226 	result->offset_rgba = input[2].offset_rgba;
   227 	return;
   228     }
   229     float t = ((result->x - input[1].x) * sy -
   230 	       (result->y - input[1].y) * sx) / detxy;
   231     float s = ((result->y - input[1].y) * tx -
   232 	       (result->x - input[1].x) * ty) / detxy;
   234     float sz = input[2].z - input[1].z;
   235     float tz = input[0].z - input[1].z;
   236     float su = input[2].u - input[1].u;
   237     float tu = input[0].u - input[1].u;
   238     float sv = input[2].v - input[1].v;
   239     float tv = input[0].v - input[1].v;
   241     float rz = input[1].z + (t*tz) + (s*sz);
   242     if( rz > pvr2_scene.bounds[5] ) {
   243 	pvr2_scene.bounds[5] = rz;
   244     } else if( rz < pvr2_scene.bounds[4] ) {
   245 	pvr2_scene.bounds[4] = rz; 
   246     }
   247     result->z = rz;
   248     result->u = input[1].u + (t*tu) + (s*su);
   249     result->v = input[1].v + (t*tv) + (s*sv);
   251     if( is_solid_shaded ) {
   252 	result->rgba = input[2].rgba;
   253 	result->offset_rgba = input[2].offset_rgba;
   254     } else {
   255 	uint8_t *rgba0 = (uint8_t *)&input[0].rgba;
   256 	uint8_t *rgba1 = (uint8_t *)&input[1].rgba;
   257 	uint8_t *rgba2 = (uint8_t *)&input[2].rgba;
   258 	uint8_t *rgba3 = (uint8_t *)&result->rgba;
   259 	for( i=0; i<8; i++ ) { // note: depends on rgba & offset_rgba being adjacent
   260 	    float tc = *rgba0++ - *rgba1;
   261 	    float sc = *rgba2++ - *rgba1;
   262 	    float rc = *rgba1++ + (t*tc) + (s*sc);
   263 	    if( rc < 0 ) {
   264 		rc = 0;
   265 	    } else if( rc > 255 ) {
   266 		rc = 255;
   267 	    }
   268 	    *rgba3++ = rc;
   269 	}
   270     }    
   272 }
   274 static void scene_add_vertexes( pvraddr_t poly_idx, int vertex_length,
   275 					gboolean is_modified )
   276 {
   277     struct polygon_struct *poly = pvr2_scene.buf_to_poly_map[poly_idx];
   278     uint32_t *ptr = &pvr2_scene.pvr2_pbuf[poly_idx];
   279     uint32_t *context = ptr;
   280     unsigned int i;
   282     assert( poly != NULL );
   283     if( poly->vertex_index == -1 ) {
   284 	ptr += (is_modified ? 5 : 3 );
   285 	poly->vertex_index = pvr2_scene.vertex_index;
   287 	assert( pvr2_scene.vertex_index + poly->vertex_count <= pvr2_scene.vertex_count );
   288 	for( i=0; i<poly->vertex_count; i++ ) {
   289 	    pvr2_decode_render_vertex( &pvr2_scene.vertex_array[pvr2_scene.vertex_index++], context[0], context[1], ptr, 0 );
   290 	    ptr += vertex_length;
   291 	}
   292 	if( is_modified ) {
   293 	    int mod_offset = (vertex_length - 3)>>1;
   294 	    ptr = &pvr2_scene.pvr2_pbuf[poly_idx] + 5;
   295 	    poly->mod_vertex_index = pvr2_scene.vertex_index;
   296 	    for( i=0; i<poly->vertex_count; i++ ) {
   297 		pvr2_decode_render_vertex( &pvr2_scene.vertex_array[pvr2_scene.vertex_index++], context[0], context[3], ptr, mod_offset );
   298 		ptr += vertex_length;
   299 	    }
   300 	}
   301     }
   302 }
   304 static void scene_add_quad_vertexes( pvraddr_t poly_idx, int vertex_length, 
   305 					     gboolean is_modified )
   306 {
   307     struct polygon_struct *poly = pvr2_scene.buf_to_poly_map[poly_idx];
   308     uint32_t *ptr = &pvr2_scene.pvr2_pbuf[poly_idx];
   309     uint32_t *context = ptr;
   310     unsigned int i;
   312     if( poly->vertex_index == -1 ) {
   313 	// Construct it locally and copy to the vertex buffer, as the VBO is 
   314 	// allowed to be horribly slow for reads (ie it could be direct-mapped
   315 	// vram).
   316 	struct vertex_struct quad[4];
   318 	assert( poly != NULL );
   319 	ptr += (is_modified ? 5 : 3 );
   320 	poly->vertex_index = pvr2_scene.vertex_index;
   321 	for( i=0; i<4; i++ ) {
   322 	    pvr2_decode_render_vertex( &quad[i], context[0], context[1], ptr, 0 );
   323 	    ptr += vertex_length;
   324 	}
   325 	scene_compute_vertex( &quad[3], &quad[0], !POLY1_GOURAUD_SHADED(context[0]) );
   326 	// Swap last two vertexes (quad arrangement => tri strip arrangement)
   327 	memcpy( &pvr2_scene.vertex_array[pvr2_scene.vertex_index], quad, sizeof(struct vertex_struct)*2 );
   328 	memcpy( &pvr2_scene.vertex_array[pvr2_scene.vertex_index+2], &quad[3], sizeof(struct vertex_struct) );
   329 	memcpy( &pvr2_scene.vertex_array[pvr2_scene.vertex_index+3], &quad[2], sizeof(struct vertex_struct) );
   330 	pvr2_scene.vertex_index += 4;
   332 	if( is_modified ) {
   333 	    int mod_offset = (vertex_length - 3)>>1;
   334 	    ptr = &pvr2_scene.pvr2_pbuf[poly_idx] + 5;
   335 	    poly->mod_vertex_index = pvr2_scene.vertex_index;
   336 	    for( i=0; i<4; i++ ) {
   337 		pvr2_decode_render_vertex( &quad[4], context[0], context[3], ptr, mod_offset );
   338 		ptr += vertex_length;
   339 	    }
   340 	    scene_compute_vertex( &quad[3], &quad[0], !POLY1_GOURAUD_SHADED(context[0]) );
   341 	    memcpy( &pvr2_scene.vertex_array[pvr2_scene.vertex_index], quad, sizeof(struct vertex_struct)*2 );
   342 	    memcpy( &pvr2_scene.vertex_array[pvr2_scene.vertex_index+2], &quad[3], sizeof(struct vertex_struct) );
   343 	    memcpy( &pvr2_scene.vertex_array[pvr2_scene.vertex_index+3], &quad[2], sizeof(struct vertex_struct) );
   344 	    pvr2_scene.vertex_index += 4;
   345 	}
   346     }
   347 }
   349 static void scene_extract_polygons( pvraddr_t tile_entry )
   350 {
   351     uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);
   352     do {
   353 	uint32_t entry = *tile_list++;
   354 	if( entry >> 28 == 0x0F ) {
   355 	    break;
   356 	} else if( entry >> 28 == 0x0E ) {
   357 	    tile_list = (uint32_t *)(video_base + (entry&0x007FFFFF));
   358 	} else {
   359 	    pvraddr_t polyaddr = entry&0x000FFFFF;
   360 	    int is_modified = (entry & 0x01000000) && pvr2_scene.full_shadow;
   361 	    int vertex_length = (entry >> 21) & 0x07;
   362 	    int context_length = 3;
   363 	    if( is_modified ) {
   364 		context_length = 5;
   365 		vertex_length <<= 1 ;
   366 	    }
   367 	    vertex_length += 3;
   369 	    if( (entry & 0xE0000000) == 0x80000000 ) {
   370 		/* Triangle(s) */
   371 		int strip_count = ((entry >> 25) & 0x0F)+1;
   372 		int polygon_length = 3 * vertex_length + context_length;
   373 		int i;
   374 		struct polygon_struct *last_poly = NULL;
   375 		for( i=0; i<strip_count; i++ ) {
   376 		    struct polygon_struct *poly = scene_add_polygon( polyaddr, 3, is_modified );
   377 		    polyaddr += polygon_length;
   378 		    if( last_poly != NULL && last_poly->next == NULL ) {
   379 			last_poly->next = poly;
   380 		    }
   381 		    last_poly = poly;
   382 		}
   383 	    } else if( (entry & 0xE0000000) == 0xA0000000 ) {
   384 		/* Sprite(s) */
   385 		int strip_count = ((entry >> 25) & 0x0F)+1;
   386 		int polygon_length = 4 * vertex_length + context_length;
   387 		int i;
   388 		struct polygon_struct *last_poly = NULL;
   389 		for( i=0; i<strip_count; i++ ) {
   390 		    struct polygon_struct *poly = scene_add_polygon( polyaddr, 4, is_modified );
   391 		    polyaddr += polygon_length;
   392 		    if( last_poly != NULL && last_poly->next == NULL ) {
   393 			last_poly->next = poly;
   394 		    }
   395 		    last_poly = poly;
   396 		}
   397 	    } else {
   398 		/* Polygon */
   399 		int i, last = -1;
   400 		for( i=5; i>=0; i-- ) {
   401 		    if( entry & (0x40000000>>i) ) {
   402 			last = i;
   403 			break;
   404 		    }
   405 		}
   406 		if( last != -1 ) {
   407 		    scene_add_polygon( polyaddr, last+3, is_modified );
   408 		}
   409 	    }
   410 	}
   411     } while( 1 );
   412 }
   414 static void scene_extract_vertexes( pvraddr_t tile_entry )
   415 {
   416     uint32_t *tile_list = (uint32_t *)(video_base+tile_entry);
   417     do {
   418 	uint32_t entry = *tile_list++;
   419 	if( entry >> 28 == 0x0F ) {
   420 	    break;
   421 	} else if( entry >> 28 == 0x0E ) {
   422 	    tile_list = (uint32_t *)(video_base + (entry&0x007FFFFF));
   423 	} else {
   424 	    pvraddr_t polyaddr = entry&0x000FFFFF;
   425 	    int is_modified = (entry & 0x01000000) && pvr2_scene.full_shadow;
   426 	    int vertex_length = (entry >> 21) & 0x07;
   427 	    int context_length = 3;
   428 	    if( is_modified ) {
   429 		context_length = 5;
   430 		vertex_length <<=1 ;
   431 	    }
   432 	    vertex_length += 3;
   434 	    if( (entry & 0xE0000000) == 0x80000000 ) {
   435 		/* Triangle(s) */
   436 		int strip_count = ((entry >> 25) & 0x0F)+1;
   437 		int polygon_length = 3 * vertex_length + context_length;
   438 		int i;
   439 		for( i=0; i<strip_count; i++ ) {
   440 		    scene_add_vertexes( polyaddr, vertex_length, is_modified );
   441 		    polyaddr += polygon_length;
   442 		}
   443 	    } else if( (entry & 0xE0000000) == 0xA0000000 ) {
   444 		/* Sprite(s) */
   445 		int strip_count = ((entry >> 25) & 0x0F)+1;
   446 		int polygon_length = 4 * vertex_length + context_length;
   447 		int i;
   448 		for( i=0; i<strip_count; i++ ) {
   449 		    scene_add_quad_vertexes( polyaddr, vertex_length, is_modified );
   450 		    polyaddr += polygon_length;
   451 		}
   452 	    } else {
   453 		/* Polygon */
   454 		int i, last = -1;
   455 		for( i=5; i>=0; i-- ) {
   456 		    if( entry & (0x40000000>>i) ) {
   457 			last = i;
   458 			break;
   459 		    }
   460 		}
   461 		if( last != -1 ) {
   462 		    scene_add_vertexes( polyaddr, vertex_length, is_modified );
   463 		}
   464 	    }
   465 	}
   466     } while( 1 );    
   467 }
   469 uint32_t pvr2_scene_buffer_width()
   470 {
   471     return pvr2_scene.buffer_width;
   472 }
   474 uint32_t pvr2_scene_buffer_height()
   475 {
   476     return pvr2_scene.buffer_height;
   477 }
   479 /**
   480  * Extract the current scene into the rendering structures. We run two passes
   481  * - first pass extracts the polygons into pvr2_scene.poly_array (finding vertex counts), 
   482  * second pass extracts the vertex data into the VBO/vertex array.
   483  *
   484  * Difficult to do in single pass as we don't generally know the size of a 
   485  * polygon for certain until we've seen all tiles containing it. It also means we
   486  * can count the vertexes and allocate the appropriate size VBO.
   487  *
   488  * FIXME: accesses into VRAM need to be bounds-checked properly
   489  */
   490 void pvr2_scene_read( void )
   491 {
   492     pvr2_scene_init();
   493     pvr2_scene_reset();
   495     pvr2_scene.bounds[0] = MMIO_READ( PVR2, RENDER_HCLIP ) & 0x03FF;
   496     pvr2_scene.bounds[1] = ((MMIO_READ( PVR2, RENDER_HCLIP ) >> 16) & 0x03FF) + 1;
   497     pvr2_scene.bounds[2] = MMIO_READ( PVR2, RENDER_VCLIP ) & 0x03FF;
   498     pvr2_scene.bounds[3] = ((MMIO_READ( PVR2, RENDER_VCLIP ) >> 16) & 0x03FF) + 1;
   499     pvr2_scene.bounds[4] = pvr2_scene.bounds[5] = MMIO_READF( PVR2, RENDER_FARCLIP );
   501     uint32_t *tilebuffer = (uint32_t *)(video_base + MMIO_READ( PVR2, RENDER_TILEBASE ));
   502     uint32_t *segment = tilebuffer;
   503     pvr2_scene.segment_list = (struct tile_segment *)tilebuffer;
   504     pvr2_scene.pvr2_pbuf = (uint32_t *)(video_base + MMIO_READ(PVR2,RENDER_POLYBASE));
   505     pvr2_scene.full_shadow = MMIO_READ( PVR2, RENDER_SHADOW ) & 0x100 ? FALSE : TRUE;
   507     int max_tile_x = 0;
   508     int max_tile_y = 0;
   509     int obj_config = MMIO_READ( PVR2, RENDER_OBJCFG );
   510     int isp_config = MMIO_READ( PVR2, RENDER_ISPCFG );
   512     if( (obj_config & 0x00200000) == 0 ) {
   513 	if( isp_config & 1 ) {
   514 	    pvr2_scene.sort_mode = SORT_NEVER;
   515 	} else {
   516 	    pvr2_scene.sort_mode = SORT_ALWAYS;
   517 	}
   518     } else {
   519 	pvr2_scene.sort_mode = SORT_BYFLAG;
   520     }
   522     // Pass 1: Extract polygon list 
   523     uint32_t control;
   524     int i;
   525     do {
   526 	control = *segment++;
   527 	int tile_x = SEGMENT_X(control);
   528 	int tile_y = SEGMENT_Y(control);
   529 	if( tile_x > max_tile_x ) {
   530 	    max_tile_x = tile_x;
   531 	} 
   532 	if( tile_y > max_tile_y ) {
   533 	    max_tile_y = tile_y;
   534 	}
   535 	for( i=0; i<5; i++ ) {
   536 	    if( (*segment & NO_POINTER) == 0 ) {
   537 		scene_extract_polygons( *segment );
   538 	    }
   539 	    segment++;
   540 	}
   541     } while( (control & SEGMENT_END) == 0 );
   543     pvr2_scene.buffer_width = (max_tile_x+1)<<5;
   544     pvr2_scene.buffer_height = (max_tile_y+1)<<5;
   546     if( pvr2_scene.vertex_count > 0 ) {
   547 	// Pass 2: Extract vertex data
   548 	vertex_buffer_map();
   549 	pvr2_scene.vertex_index = 0;
   550 	segment = tilebuffer;
   551 	do {
   552 	    control = *segment++;
   553 	    for( i=0; i<5; i++ ) {
   554 		if( (*segment & NO_POINTER) == 0 ) {
   555 		    scene_extract_vertexes( *segment );
   556 		}
   557 		segment++;
   558 	    }
   559 	} while( (control & SEGMENT_END) == 0 );
   561 	vertex_buffer_unmap();
   562     }
   563 }
.