<html>
<body>
  <div id="body" style="background-color:#ffffff;" >
<table cellspacing="0" cellpadding="0" border="0" rules="cols">
<tr class="head" style="border-bottom-width:1px;border-bottom-style:solid;" ><td class="headtd" style="padding:0;padding-top:.2em;" colspan="4">Commit in <b><tt>lxdream/src/pvr2</tt></b></td></tr>
<tr><td><tt><a href="#file1">glrender.c</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+38</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-39</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">1e074a98317c -> f3da7d810d5c</td></tr>
<tr class="alt" style=";" ><td><tt><a href="#file2">rendsort.c</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+22</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-19</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">1e074a98317c -> f3da7d810d5c</td></tr>
<tr><td><tt><a href="#file3">scene.c</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+88</td><td></td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">1e074a98317c -> f3da7d810d5c</td></tr>
<tr class="alt" style=";" ><td><tt><a href="#file4">scene.h</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+4</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-2</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">1e074a98317c -> f3da7d810d5c</td></tr>
<tr><td></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+152</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-60</td><td></td></tr>
</table>
<small id="info" style="color: #888888;" >4 modified files</small><br />
<div class="tasklist" style="padding:4px;border:1px dashed #000000;margin-top:1em;" ><ul>
<li><a href="#task1">FIXME: This could end up including a triangle that was</a></li>
</ul></div>
<pre class="comment" style="white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;padding:4px;border:1px dashed #000000;background-color:#ffffdd;" >
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.
</pre>
<hr /><a name="file1" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/pvr2</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>glrender.c</b></big> <small id="info" style="color: #888888;" >1e074a98317c -> f3da7d810d5c</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/pvr2/glrender.c
+++ lxdream/src/pvr2/glrender.c
@@ -101,7 +101,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 
     texcache_gl_init(); // Allocate texture IDs
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    glCullFace( GL_BACK );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    glDisable( GL_CULL_FACE );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     glEnable( GL_BLEND );
     glEnable( GL_DEPTH_TEST );
     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -131,24 +131,6 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     glFogf(GL_FOG_END, 1.0);
 }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-static void render_set_cull( uint32_t poly1 )
-{
-    switch( POLY1_CULL_MODE(poly1) ) {
-    case CULL_NONE:
-    case CULL_SMALL:
-        glDisable( GL_CULL_FACE );
-        break;
-    case CULL_CCW:
-        glEnable( GL_CULL_FACE );
-        glFrontFace( GL_CW );
-        break;
-    case CULL_CW:
-        glEnable( GL_CULL_FACE );
-        glFrontFace( GL_CCW );
-        break;
-    }   
-}    
-
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > /**
  * Setup the basic context that's shared between normal and modified modes -
  * depth, culling
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -162,7 +144,6 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 
     glDepthMask( POLY1_DEPTH_WRITE(poly1) ? GL_TRUE : GL_FALSE );
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    render_set_cull( poly1 );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
 
 /**
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -223,22 +204,40 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     render_set_tsp_context(context[0],context[1],context[2]);
 }
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static inline void gl_draw_vertexes( struct polygon_struct *poly )
+{
+    do {
+        glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index, poly->vertex_count);
+        poly = poly->sub_next;
+    } while( poly != NULL );
+}
+
+static inline void gl_draw_mod_vertexes( struct polygon_struct *poly )
+{
+    do {
+        glDrawArrays(GL_TRIANGLE_STRIP, poly->mod_vertex_index, poly->vertex_count);
+        poly = poly->sub_next;
+    } while( poly != NULL );
+}
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 static void gl_render_poly( struct polygon_struct *poly, GLint depth_mode )
 {
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    if( poly->vertex_count == 0 )
+        return; /* Culled */
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     if( poly->tex_id != -1 ) {
         glBindTexture(GL_TEXTURE_2D, poly->tex_id);
     }
     if( poly->mod_vertex_index == -1 ) {
         glDisable( GL_STENCIL_TEST );
         render_set_context( poly->context, depth_mode );
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index, poly->vertex_count );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        gl_draw_vertexes(poly);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }  else {
         glEnable( GL_STENCIL_TEST );
         render_set_base_context( poly->context[0], depth_mode );
         render_set_tsp_context( poly->context[0], poly->context[1], poly->context[2] );
         glStencilFunc(GL_EQUAL, 0, 2);
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index, poly->vertex_count );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        gl_draw_vertexes(poly);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
         if( pvr2_scene.shadow_mode == SHADOW_FULL ) {
             if( poly->mod_tex_id != -1 ) {
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -247,7 +246,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             render_set_tsp_context( poly->context[0], poly->context[3], poly->context[4] );
         }
         glStencilFunc(GL_EQUAL, 2, 2);
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        glDrawArrays(GL_TRIANGLE_STRIP, poly->mod_vertex_index, poly->vertex_count );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        gl_draw_mod_vertexes(poly);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 }
 
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -258,10 +257,8 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
     render_set_context( poly->context, 0 );
     glDisable( GL_DEPTH_TEST );
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    glDisable( GL_CULL_FACE );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     glBlendFunc( GL_ONE, GL_ZERO );
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index, poly->vertex_count );
-    glEnable( GL_CULL_FACE );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    gl_draw_vertexes(poly);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     glEnable( GL_DEPTH_TEST );
 }
 
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -327,8 +324,10 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             strip_count = ((entry >> 25) & 0x0F)+1;
             poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];
             while( strip_count > 0 ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-                render_set_base_context(poly->context[0],0);
-                glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index, poly->vertex_count );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+                if( poly->vertex_count != 0 ) {
+                    render_set_base_context(poly->context[0],0);
+                    gl_draw_vertexes(poly);
+                }
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >                 poly = poly->next;
                 strip_count--;
             }
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -336,8 +335,10 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         default:
             if( entry & 0x7E000000 ) {
                 poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-                render_set_base_context(poly->context[0],0);
-                glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index, poly->vertex_count );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+                if( poly->vertex_count != 0 ) {
+                    render_set_base_context(poly->context[0],0);
+                    gl_draw_vertexes(poly);
+                }
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             }
         }
     }           
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -368,8 +369,12 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >      * now :)
      */
     
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    render_set_cull(poly->context[0]);
-    glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index, poly->vertex_count );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    if( poly->vertex_count == 0 )
+        return; /* Culled */
+
+    gl_draw_vertexes(poly);
+
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     
     int poly_type = POLY1_VOLUME_MODE(poly->context[0]);
     if( poly_type == PVR2_VOLUME_REGION0 ) {
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -381,7 +386,6 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         glStencilMask( 0x03 );
         glStencilFunc(GL_EQUAL, 0x02, 0x03);
         glStencilOp(GL_ZERO, GL_KEEP, GL_KEEP);
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        glDisable( GL_CULL_FACE );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         glDisable( GL_DEPTH_TEST );
 
         drawrect2d( tile_bounds, pvr2_scene.bounds[4] );
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -399,7 +403,6 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >          */
         glStencilMask( 0x02 );
         glStencilOp( GL_INVERT, GL_INVERT, GL_INVERT );
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        glDisable( GL_CULL_FACE );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         glDisable( GL_DEPTH_TEST );
         
         drawrect2d( tile_bounds, pvr2_scene.bounds[4] );
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -427,7 +430,6 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         return;
 
     glDisable( GL_TEXTURE_2D );
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    glDisable( GL_CULL_FACE );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     glEnable( GL_STENCIL_TEST );
     glEnable( GL_DEPTH_TEST );
     glDepthFunc( GL_LEQUAL );
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -552,10 +554,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             gl_render_tilelist(segment->punchout_ptr, GL_GEQUAL );
             glDisable(GL_ALPHA_TEST );
         }
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        glDisable( GL_STENCIL_TEST );
-        glStencilMask(0x03);
-        glClear( GL_STENCIL_BUFFER_BIT );
-        
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         if( IS_TILE_PTR(segment->trans_ptr) ) {
             if( pvr2_scene.sort_mode == SORT_NEVER || 
                     (pvr2_scene.sort_mode == SORT_TILEFLAG && (segment->control&SEGMENT_SORT_TRANS))) {
</pre></div>
<hr /><a name="file2" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/pvr2</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>rendsort.c</b></big> <small id="info" style="color: #888888;" >1e074a98317c -> f3da7d810d5c</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/pvr2/rendsort.c
+++ lxdream/src/pvr2/rendsort.c
@@ -38,7 +38,8 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 /**
  * Count the number of triangles in the list starting at the given 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >- * pvr memory address.
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ * pvr memory address. This is an upper bound as it includes
+ * triangles that have been culled out.
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  */
 static int sort_count_triangles( pvraddr_t tile_entry ) {
     uint32_t *tile_list = (uint32_t *)(pvr2_main_ram+tile_entry);
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -54,11 +55,11 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         } else if( entry >> 29 == 0x05 ) { /* Quad array */
             count += ((((entry >> 25) & 0x0F)+1)<<1);
         } else { /* Polygon */
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-            int i;
-            for( i=0; i<6; i++ ) {
-                if( entry & (0x40000000>>i) ) {
-                    count++;
-                }
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+            struct polygon_struct *poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];
+            while( poly != NULL ) {
+                if( poly->vertex_count != 0 )
+                    count += poly->vertex_count-2;
+                poly = poly->sub_next;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             }
         }
     }
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -94,6 +95,8 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >                   vertexes[0].z*triangle->mz;
 }
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > /**
  * Extract a triangle list from the tile (basically indexes into the polygon list, plus
  * computing maxz while we go through it
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -118,7 +121,8 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];
             while( strip_count > 0 ) {
                 assert( poly != NULL );
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-                for( i=0; i<poly->vertex_count-2; i++ ) {
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+                for( i=0; i+2<poly->vertex_count; i++ ) {
+                    /* Note: tris + quads can't have sub-polys */
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >                     sort_add_triangle( &triangles[count], poly, i );
                     count++;
                 }
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -129,11 +133,17 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         default:
             if( entry & 0x7E000000 ) {
                 poly = pvr2_scene.buf_to_poly_map[entry&0x000FFFFF];
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-                for( i=0; i<6; i++ ) {
-                    if( entry & (0x40000000>>i) ) {
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" ><a name="task1" />+                /* <span class="task" style="background-color:#ffff00;" >FIXME</span>: This could end up including a triangle that was
+                 * excluded from the tile, if it is part of a strip that
+                 * still has some other triangles in the tile.
+                 * (This couldn't happen with TA output though).
+                 */
+                while( poly != NULL ) {
+                    for( i=0; i+2<poly->vertex_count; i++ ) {
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >                         sort_add_triangle( &triangles[count], poly, i );
                         count++;
                     }
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+                    poly = poly->sub_next;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >                 }
             }
         }
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -151,13 +161,6 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         }
         render_set_context( poly->context, GL_GEQUAL );
         glDepthMask(GL_FALSE);
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        /* Fix cull direction */
-        if( triangles[i]->triangle_num & 1 ) {
-            glCullFace(GL_FRONT);
-        } else {
-            glCullFace(GL_BACK);
-        }
-
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         glDrawArrays(GL_TRIANGLE_STRIP, poly->vertex_index + triangles[i]->triangle_num, 3 );
     }
 }
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -263,9 +266,9 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             triangle_order[i] = &triangles[i];
         }
         int extracted_triangles = sort_extract_triangles(tile_entry, triangles);
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        assert( extracted_triangles == num_triangles );
-        sort_triangles( triangle_order, num_triangles, triangle_order );
-        sort_render_triangles(triangle_order, num_triangles);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        assert( extracted_triangles <= num_triangles );
+        sort_triangles( triangle_order, extracted_triangles, triangle_order );
+        sort_render_triangles(triangle_order, extracted_triangles);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         glCullFace(GL_BACK);
         assert( triangles[num_triangles].poly == (void *)SENTINEL );
     }
</pre></div>
<hr /><a name="file3" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/pvr2</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>scene.c</b></big> <small id="info" style="color: #888888;" >1e074a98317c -> f3da7d810d5c</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/pvr2/scene.c
+++ lxdream/src/pvr2/scene.c
@@ -192,6 +192,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         poly->vertex_index = -1;
         poly->mod_vertex_index = -1;
         poly->next = NULL;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        poly->sub_next = NULL;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         pvr2_scene.buf_to_poly_map[poly_idx] = poly;
         pvr2_scene.vertex_count += (vertex_count * vert_mul);
         return poly;
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -199,6 +200,33 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
 
 /**
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ * Given a starting polygon, break it at the specified triangle so that the
+ * preceding triangles are retained, and the remainder are contained in a
+ * new sub-polygon. Does not preserve winding.
+ */
+static struct polygon_struct *scene_split_subpolygon( struct polygon_struct *parent, int split_offset )
+{
+    assert( split_offset > 0 && split_offset < (parent->vertex_count-2) );
+    assert( pvr2_scene.poly_count < MAX_POLYGONS );
+    struct polygon_struct *poly = &pvr2_scene.poly_array[pvr2_scene.poly_count++];
+    poly->vertex_count = parent->vertex_count - split_offset;
+    poly->vertex_index = parent->vertex_index + split_offset;
+    if( parent->mod_vertex_index == -1 ) {
+        poly->mod_vertex_index = -1;
+    } else {
+        poly->mod_vertex_index = parent->mod_vertex_index + split_offset;
+    }
+    poly->context = parent->context;
+    poly->next = NULL;
+    poly->sub_next = parent->sub_next;
+
+    parent->sub_next = poly;
+    parent->vertex_count = split_offset + 2;
+
+    return poly;
+}
+
+/**
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  * Decode a single PVR2 renderable vertex (opaque/trans/punch-out, but not shadow
  * volume)
  * @param vert Pointer to output vertex structure
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -395,6 +423,64 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }    
 }
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+/**
+ * Manually cull back-facing polygons where we can - this actually saves
+ * us a lot of time vs passing everything to GL to do it.
+ */
+static void scene_backface_cull()
+{
+    unsigned poly_idx;
+    unsigned poly_count = pvr2_scene.poly_count; /* Note: we don't want to process any sub-polygons created here */
+    for( poly_idx = 0; poly_idx<poly_count; poly_idx++ ) {
+        uint32_t poly1 = pvr2_scene.poly_array[poly_idx].context[0];
+        if( POLY1_CULL_ENABLE(poly1) ) {
+            struct polygon_struct *poly = &pvr2_scene.poly_array[poly_idx];
+            unsigned vert_idx = poly->vertex_index;
+            unsigned tri_count = poly->vertex_count-2;
+            struct vertex_struct *vert = &pvr2_scene.vertex_array[vert_idx];
+            unsigned i;
+            gboolean ccw = (POLY1_CULL_MODE(poly1) == CULL_CCW);
+            int first_visible = -1, last_visible = -1;
+            for( i=0; i<tri_count; i++ ) {
+                float ux = vert[i+1].x - vert[i].x;
+                float uy = vert[i+1].y - vert[i].y;
+                float vx = vert[i+2].x - vert[i].x;
+                float vy = vert[i+2].y - vert[i].y;
+                float nz = (ux*vy) - (uy*vx);
+                if( ccw ? nz > 0 : nz < 0 ) {
+                    /* Surface is visible */
+                    if( first_visible == -1 ) {
+                        first_visible = i;
+                        /* Elide the initial hidden triangles (note we don't
+                         * need to care about winding anymore here) */
+                        poly->vertex_index += i;
+                        poly->vertex_count -= i;
+                        if( poly->mod_vertex_index != -1 )
+                            poly->mod_vertex_index += i;
+                    } else if( last_visible != i-1 ) {
+                        /* And... here we have to split the polygon. Allocate a new
+                         * sub-polygon to hold the vertex references */
+                        struct polygon_struct *sub = scene_split_subpolygon(poly, (i-first_visible));
+                        poly->vertex_count -= (i-first_visible-1) - last_visible;
+                        first_visible = i;
+                        poly = sub;
+                    }
+                    last_visible = i;
+                } /* Else culled */
+                /* Invert ccw flag for triangle strip processing */
+                ccw = !ccw;
+            }
+            if( last_visible == -1 ) {
+                /* No visible surfaces, so we can mark the whole polygon as being vertex-less */
+                poly->vertex_count = 0;
+            } else if( last_visible != tri_count-1 ) {
+                /* Remove final hidden tris */
+                poly->vertex_count -= (tri_count - 1 - last_visible);
+            }
+        }
+    }
+}
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > static void scene_add_cheap_shadow_vertexes( struct vertex_struct *src, struct vertex_struct *dest, int count )
 {
     unsigned int i, j;
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -655,6 +741,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     context_length += (bgplane & 0x07) * vertex_length;
 
     poly->next = NULL;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    poly->sub_next = NULL;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     pvr2_scene.bkgnd_poly = poly;
 
     struct vertex_struct base_vertexes[3];
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -804,6 +891,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
     scene_extract_background();
     scene_compute_lut_fog();
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    scene_backface_cull();
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
     vertex_buffer_unmap();
 }
</pre></div>
<hr /><a name="file4" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/pvr2</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>scene.h</b></big> <small id="info" style="color: #888888;" >1e074a98317c -> f3da7d810d5c</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/pvr2/scene.h
+++ lxdream/src/pvr2/scene.h
@@ -49,6 +49,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     uint32_t mod_tex_id;
     int32_t mod_vertex_index; // index of first modified vertex in vertex buffer
     struct polygon_struct *next; // chain for tri/quad arrays
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    struct polygon_struct *sub_next; // chain for internal sub-polygons
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > };
 
 void pvr2_scene_init(void);
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -74,10 +75,11 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 /**
  * Maximum polygons - smallest is 1 polygon in 48 bytes, giving
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >- * 87381, plus 1 for the background
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ * 87381, plus 1 for the background. Allow the same amount again
+ * for split polygons (worst case)
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  * 
  */
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-#define MAX_POLYGONS <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >87382</span>
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#define MAX_POLYGONS <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >(87382*2)</span>
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #define MAX_POLY_BUFFER_SIZE (MAX_POLYGONS*sizeof(struct polygon_struct))
 #define BUF_POLY_MAP_SIZE (4 MB)
 
</pre></div>
<center><small>Chaos Theory</small></center>
</div></body></html>