Search
lxdream.org :: lxdream/src/pvr2/scene.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/scene.c
changeset 1133:f3da7d810d5c
prev1132:1e074a98317c
next1139:9af81878480b
author nkeynes
date Wed Oct 20 17:56:59 2010 +1000 (9 years ago)
permissions -rw-r--r--
last change Perform backface culling in scene preparation rather than leaving it to the
GL - this is a huge performance win, at least on the 9400M - changing cull
state appears to be very expensive, whereas the CPU needed to do the same
job is only just barely measurable.
file annotate diff log raw
1.1 --- a/src/pvr2/scene.c Tue Oct 19 22:43:10 2010 +1000
1.2 +++ b/src/pvr2/scene.c Wed Oct 20 17:56:59 2010 +1000
1.3 @@ -192,6 +192,7 @@
1.4 poly->vertex_index = -1;
1.5 poly->mod_vertex_index = -1;
1.6 poly->next = NULL;
1.7 + poly->sub_next = NULL;
1.8 pvr2_scene.buf_to_poly_map[poly_idx] = poly;
1.9 pvr2_scene.vertex_count += (vertex_count * vert_mul);
1.10 return poly;
1.11 @@ -199,6 +200,33 @@
1.12 }
1.13
1.14 /**
1.15 + * Given a starting polygon, break it at the specified triangle so that the
1.16 + * preceding triangles are retained, and the remainder are contained in a
1.17 + * new sub-polygon. Does not preserve winding.
1.18 + */
1.19 +static struct polygon_struct *scene_split_subpolygon( struct polygon_struct *parent, int split_offset )
1.20 +{
1.21 + assert( split_offset > 0 && split_offset < (parent->vertex_count-2) );
1.22 + assert( pvr2_scene.poly_count < MAX_POLYGONS );
1.23 + struct polygon_struct *poly = &pvr2_scene.poly_array[pvr2_scene.poly_count++];
1.24 + poly->vertex_count = parent->vertex_count - split_offset;
1.25 + poly->vertex_index = parent->vertex_index + split_offset;
1.26 + if( parent->mod_vertex_index == -1 ) {
1.27 + poly->mod_vertex_index = -1;
1.28 + } else {
1.29 + poly->mod_vertex_index = parent->mod_vertex_index + split_offset;
1.30 + }
1.31 + poly->context = parent->context;
1.32 + poly->next = NULL;
1.33 + poly->sub_next = parent->sub_next;
1.34 +
1.35 + parent->sub_next = poly;
1.36 + parent->vertex_count = split_offset + 2;
1.37 +
1.38 + return poly;
1.39 +}
1.40 +
1.41 +/**
1.42 * Decode a single PVR2 renderable vertex (opaque/trans/punch-out, but not shadow
1.43 * volume)
1.44 * @param vert Pointer to output vertex structure
1.45 @@ -395,6 +423,64 @@
1.46 }
1.47 }
1.48
1.49 +/**
1.50 + * Manually cull back-facing polygons where we can - this actually saves
1.51 + * us a lot of time vs passing everything to GL to do it.
1.52 + */
1.53 +static void scene_backface_cull()
1.54 +{
1.55 + unsigned poly_idx;
1.56 + unsigned poly_count = pvr2_scene.poly_count; /* Note: we don't want to process any sub-polygons created here */
1.57 + for( poly_idx = 0; poly_idx<poly_count; poly_idx++ ) {
1.58 + uint32_t poly1 = pvr2_scene.poly_array[poly_idx].context[0];
1.59 + if( POLY1_CULL_ENABLE(poly1) ) {
1.60 + struct polygon_struct *poly = &pvr2_scene.poly_array[poly_idx];
1.61 + unsigned vert_idx = poly->vertex_index;
1.62 + unsigned tri_count = poly->vertex_count-2;
1.63 + struct vertex_struct *vert = &pvr2_scene.vertex_array[vert_idx];
1.64 + unsigned i;
1.65 + gboolean ccw = (POLY1_CULL_MODE(poly1) == CULL_CCW);
1.66 + int first_visible = -1, last_visible = -1;
1.67 + for( i=0; i<tri_count; i++ ) {
1.68 + float ux = vert[i+1].x - vert[i].x;
1.69 + float uy = vert[i+1].y - vert[i].y;
1.70 + float vx = vert[i+2].x - vert[i].x;
1.71 + float vy = vert[i+2].y - vert[i].y;
1.72 + float nz = (ux*vy) - (uy*vx);
1.73 + if( ccw ? nz > 0 : nz < 0 ) {
1.74 + /* Surface is visible */
1.75 + if( first_visible == -1 ) {
1.76 + first_visible = i;
1.77 + /* Elide the initial hidden triangles (note we don't
1.78 + * need to care about winding anymore here) */
1.79 + poly->vertex_index += i;
1.80 + poly->vertex_count -= i;
1.81 + if( poly->mod_vertex_index != -1 )
1.82 + poly->mod_vertex_index += i;
1.83 + } else if( last_visible != i-1 ) {
1.84 + /* And... here we have to split the polygon. Allocate a new
1.85 + * sub-polygon to hold the vertex references */
1.86 + struct polygon_struct *sub = scene_split_subpolygon(poly, (i-first_visible));
1.87 + poly->vertex_count -= (i-first_visible-1) - last_visible;
1.88 + first_visible = i;
1.89 + poly = sub;
1.90 + }
1.91 + last_visible = i;
1.92 + } /* Else culled */
1.93 + /* Invert ccw flag for triangle strip processing */
1.94 + ccw = !ccw;
1.95 + }
1.96 + if( last_visible == -1 ) {
1.97 + /* No visible surfaces, so we can mark the whole polygon as being vertex-less */
1.98 + poly->vertex_count = 0;
1.99 + } else if( last_visible != tri_count-1 ) {
1.100 + /* Remove final hidden tris */
1.101 + poly->vertex_count -= (tri_count - 1 - last_visible);
1.102 + }
1.103 + }
1.104 + }
1.105 +}
1.106 +
1.107 static void scene_add_cheap_shadow_vertexes( struct vertex_struct *src, struct vertex_struct *dest, int count )
1.108 {
1.109 unsigned int i, j;
1.110 @@ -655,6 +741,7 @@
1.111 context_length += (bgplane & 0x07) * vertex_length;
1.112
1.113 poly->next = NULL;
1.114 + poly->sub_next = NULL;
1.115 pvr2_scene.bkgnd_poly = poly;
1.116
1.117 struct vertex_struct base_vertexes[3];
1.118 @@ -804,6 +891,7 @@
1.119
1.120 scene_extract_background();
1.121 scene_compute_lut_fog();
1.122 + scene_backface_cull();
1.123
1.124 vertex_buffer_unmap();
1.125 }
.