<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">+233</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-102</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">d63c808ddcd3 -> e5b12e2fe6ba</td></tr>
<tr class="alt" style=";" ><td><tt><a href="#file2">shaders.glsl</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+42</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">d63c808ddcd3 -> e5b12e2fe6ba</td></tr>
<tr><td></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+275</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-121</td><td></td></tr>
</table>
<small id="info" style="color: #888888;" >2 modified files</small><br />
<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;" >
Remove most of the remaining fixed-functionality in the shader rendering
path.
Rearrange the renderer to do each list for the full scene in turn, rather
than doing each tile completely
</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;" >d63c808ddcd3 -> e5b12e2fe6ba</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/pvr2/glrender.c
+++ lxdream/src/pvr2/glrender.c
@@ -33,7 +33,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > static CGLContextObj CGL_MACRO_CONTEXT;
 #endif
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-#define IS_EMPTY_TILE_LIST(p) ((*((uint32_t *)(pvr2_main_ram+(p))) >> 28) == 0x0F)
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#define IS_NONEMPTY_TILE_LIST(p) (IS_TILE_PTR(p) && ((*((uint32_t *)(pvr2_main_ram+(p))) >> 28) != 0x0F))
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 int pvr2_poly_depthmode[8] = { GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL,
         GL_GREATER, GL_NOTEQUAL, GL_GEQUAL, 
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -62,7 +62,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  * Clip the tile bounds to the clipping plane. 
  * @return TRUE if the tile was not clipped completely.
  */
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-static gboolean clip_tile_bounds( uint32_t *tile, <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >floa</span>t *clip )
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static gboolean clip_tile_bounds( uint32_t *tile, <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >uint32_</span>t *clip )
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
     if( tile[0] < clip[0] ) tile[0] = clip[0];
     if( tile[1] > clip[1] ) tile[1] = clip[1];
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -73,11 +73,11 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 static void drawrect2d( uint32_t tile_bounds[], float z )
 {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    glBegin( GL_QUADS );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    glBegin( GL_TRIANGLE_STRIP );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     glVertex3f( tile_bounds[0], tile_bounds[2], z );
     glVertex3f( tile_bounds[1], tile_bounds[2], z );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    glVertex3f( tile_bounds[0], tile_bounds[3], z );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     glVertex3f( tile_bounds[1], tile_bounds[3], z );
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    glVertex3f( tile_bounds[0], tile_bounds[3], z );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     glEnd();
 }
 
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -112,7 +112,6 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  */
 void pvr2_setup_gl_context()
 {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     if( glsl_is_supported() && isGLMultitextureSupported() ) {
         if( !glsl_load_shaders( ) ) {
             WARN( "Unable to load GL shaders" );
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -128,9 +127,6 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     glDisable( GL_CULL_FACE );
     glEnable( GL_BLEND );
     glEnable( GL_DEPTH_TEST );
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
-    glMatrixMode(GL_MODELVIEW);
-    glLoadIdentity();
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 #ifdef HAVE_OPENGL_CLAMP_COLOR
     if( isGLExtensionSupported("GL_ARB_color_buffer_float") ) {
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -139,27 +135,14 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 #endif
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    glEnableClientState( GL_COLOR_ARRAY );
-    glEnableClientState( GL_VERTEX_ARRAY );
-    glEnableClientState( GL_TEXTURE_COORD_ARRAY );
-    glEnableClientState( GL_SECONDARY_COLOR_ARRAY );
-    glEnableClientState( GL_FOG_COORDINATE_ARRAY_EXT );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#ifdef HAVE_OPENGL_CLEAR_DEPTHF
+    glClearDepthf(0);
+#else
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     glClearDepth(0);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#endif
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     glClearStencil(0);
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-
-    glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
-    glFogi(GL_FOG_MODE, GL_LINEAR);
-    glFogf(GL_FOG_START, 0.0);
-    glFogf(GL_FOG_END, 1.0);
-
-    if( have_shaders ) {
-        glsl_use_pvr2_shader();
-        glsl_set_pvr2_shader_primary_texture(0);
-        glsl_set_pvr2_shader_palette_texture(1);
-        glsl_clear_shader();
-    }
</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;" >@@ -182,24 +165,26 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
     glShadeModel( POLY1_SHADE_MODEL(poly1) );
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#ifdef HAVE_OPENGL_FIXEDFUNC
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     if( !have_shaders ) {
         if( POLY1_TEXTURED(poly1) ) {
             if( POLY2_TEX_BLEND(poly2) == 2 )
                 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
             else
                 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+   
+         }
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        }
-    }
-
-     switch( POLY2_FOG_MODE(poly2) ) {
-     case PVR2_POLY_FOG_LOOKUP:
-         glFogfv( GL_FOG_COLOR, pvr2_scene.fog_lut_colour );
-         break;
-     case PVR2_POLY_FOG_VERTEX:
-         glFogfv( GL_FOG_COLOR, pvr2_scene.fog_vert_colour );
-         break;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+         switch( POLY2_FOG_MODE(poly2) ) {
+         case PVR2_POLY_FOG_LOOKUP:
+             glFogfv( GL_FOG_COLOR, pvr2_scene.fog_lut_colour );
+             break;
+         case PVR2_POLY_FOG_VERTEX:
+             glFogfv( GL_FOG_COLOR, pvr2_scene.fog_vert_colour );
+             break;
+         }
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >      }
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#endif
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
      int srcblend = POLY2_SRC_BLEND(poly2);
      int destblend = POLY2_DEST_BLEND(poly2);
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -387,17 +372,6 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
     tileentryiter list;
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    if( !IS_TILE_PTR(tile_entry) )
-        return;
-
-    glEnable( GL_STENCIL_TEST );
-    glEnable( GL_DEPTH_TEST );
-    glStencilFunc( GL_ALWAYS, 0, 1 );
-    glStencilOp( GL_KEEP,GL_INVERT, GL_KEEP ); 
-    glStencilMask( 0x01 );
-    glDepthFunc( GL_LEQUAL );
-    glDepthMask( GL_FALSE );
-    
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     FOREACH_TILEENTRY(list, tile_entry ) {
         struct polygon_struct *poly = pvr2_scene.buf_to_poly_map[TILEENTRYITER_POLYADDR(list)];
         if( poly != NULL ) {
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -407,9 +381,123 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             } while( list.strip_count-- > 0 );
         }
     }
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    glDepthMask( GL_TRUE );
-    glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
-    glDisable( GL_STENCIL_TEST );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+}
+
+/**
+ * Define an orthographic projection matrix
+ * Note: row-major order
+ */
+static void setOrtho( GLfloat *matrix, GLfloat width, GLfloat height, GLfloat znear, GLfloat zfar )
+{
+    matrix[0] =  2/width;
+    matrix[1] =  0;
+    matrix[2] =  0;
+    matrix[3] =  0;
+
+    matrix[4] =  0;
+    matrix[5] = -2/height;
+    matrix[6] =  0;
+    matrix[7] =  0;
+
+    matrix[8] =  0;
+    matrix[9] =  0;
+    matrix[10]= -2/(zfar-znear);
+    matrix[11]=  0;
+
+    matrix[12]= -1;
+    matrix[13]=  1;
+    matrix[14]= -(zfar+znear)/(zfar-znear);
+    matrix[15]=  1;
+}
+
+#ifdef HAVE_OPENGL_FIXEDFUNC
+void pvr2_scene_setup_fixed( GLfloat *viewMatrix )
+{
+    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
+
+    glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity();
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    glLoadMatrixf(viewMatrix);
+    
+    glEnable( GL_FOG );
+    glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
+    glFogi(GL_FOG_MODE, GL_LINEAR);
+    glFogf(GL_FOG_START, 0.0);
+    glFogf(GL_FOG_END, 1.0);
+
+    glEnable( GL_ALPHA_TEST );
+    glAlphaFunc( GL_GEQUAL, 0 );
+
+    glEnable( GL_COLOR_SUM );
+
+    glEnableClientState( GL_VERTEX_ARRAY );
+    glEnableClientState( GL_COLOR_ARRAY );
+    glEnableClientState( GL_TEXTURE_COORD_ARRAY );
+    glEnableClientState( GL_SECONDARY_COLOR_ARRAY );
+    glEnableClientState( GL_FOG_COORDINATE_ARRAY_EXT );
+
+    /* Vertex array pointers */
+    glVertexPointer(3, GL_FLOAT, sizeof(struct vertex_struct), &pvr2_scene.vertex_array[0].x);
+    glColorPointer(4, GL_FLOAT, sizeof(struct vertex_struct), &pvr2_scene.vertex_array[0].rgba[0]);
+    glTexCoordPointer(4, GL_FLOAT, sizeof(struct vertex_struct), &pvr2_scene.vertex_array[0].u);
+    glSecondaryColorPointerEXT(3, GL_FLOAT, sizeof(struct vertex_struct), pvr2_scene.vertex_array[0].offset_rgba );
+    glFogCoordPointerEXT(GL_FLOAT, sizeof(struct vertex_struct), &pvr2_scene.vertex_array[0].offset_rgba[3] );
+}
+
+void pvr2_scene_set_alpha_fixed( float alphaRef )
+{
+    glAlphaFunc( GL_GEQUAL, alphaRef );
+}
+
+void pvr2_scene_cleanup_fixed()
+{
+    glDisable( GL_COLOR_SUM );
+    glDisable( GL_FOG );
+    glDisable( GL_ALPHA_TEST );
+
+    glDisableClientState( GL_VERTEX_ARRAY );
+    glDisableClientState( GL_COLOR_ARRAY );
+    glDisableClientState( GL_TEXTURE_COORD_ARRAY );
+    glDisableClientState( GL_SECONDARY_COLOR_ARRAY );
+    glDisableClientState( GL_FOG_COORDINATE_ARRAY_EXT );
+}
+#else
+void pvr2_scene_setup_fixed( GLfloat *viewMatrix, float alphaRef )
+{
+}
+void pvr2_scene_set_alpha_fixed( float alphaRef )
+{
+}
+void pvr2_scene_cleanup_fixed()
+{
+}
+#endif
+
+void pvr2_scene_setup_shader( GLfloat *viewMatrix )
+{
+    glsl_use_pvr2_shader();
+    glsl_set_pvr2_shader_view_matrix(viewMatrix);
+    glsl_set_pvr2_shader_fog_colour1(pvr2_scene.fog_vert_colour);
+    glsl_set_pvr2_shader_fog_colour2(pvr2_scene.fog_lut_colour);
+    glsl_set_pvr2_shader_in_vertex_vec3_pointer(&pvr2_scene.vertex_array[0].x, sizeof(struct vertex_struct));
+    glsl_set_pvr2_shader_in_colour_pointer(&pvr2_scene.vertex_array[0].rgba[0], sizeof(struct vertex_struct));
+    glsl_set_pvr2_shader_in_colour2_pointer(&pvr2_scene.vertex_array[0].offset_rgba[0], sizeof(struct vertex_struct));
+    glsl_set_pvr2_shader_in_texcoord_pointer(&pvr2_scene.vertex_array[0].u, sizeof(struct vertex_struct));
+    glsl_set_pvr2_shader_alpha_ref(0.0);
+    glsl_set_pvr2_shader_primary_texture(0);
+    glsl_set_pvr2_shader_palette_texture(1);
+}
+
+void pvr2_scene_cleanup_shader( )
+{
+    glsl_clear_shader();
+}
+
+void pvr2_scene_set_alpha_shader( float alphaRef )
+{
+    glsl_set_pvr2_shader_alpha_ref(alphaRef);
</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;" >@@ -419,6 +507,10 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
     /* Scene setup */
     struct timeval start_tv, tex_tv, end_tv;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    int i;
+    GLfloat viewMatrix[16];
+    uint32_t clip_bounds[4];
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
     gettimeofday(&start_tv, NULL);
     display_driver->set_render_target(buffer);
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -429,20 +521,28 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     gettimeofday( &tex_tv, NULL );
     uint32_t ms = (tex_tv.tv_sec - start_tv.tv_sec) * 1000 +
     (tex_tv.tv_usec - start_tv.tv_usec)/1000;
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    DEBUG( "<span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >Scene setup</span> in %dms", ms );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    DEBUG( "<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >Texture load</span> in %dms", ms );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    /* Setup view projection matrix */
-    glMatrixMode(GL_PROJECTION);
-    glLoadIdentity();
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    float alphaRef = ((float)(MMIO_READ(PVR2, RENDER_ALPHA_REF)&0xFF)+1)/256.0;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     float nearz = pvr2_scene.bounds[4];
     float farz = pvr2_scene.bounds[5];
     if( nearz == farz ) {
         farz*= 4.0;
     }
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    glOrtho( 0, pvr2_scene.buffer_width, pvr2_scene.buffer_height, 0, 
-             -farz, -nearz );
-    float alphaRef = ((float)(MMIO_READ(PVR2, RENDER_ALPHA_REF)&0xFF)+1)/256.0;
-    glAlphaFunc( GL_GEQUAL, alphaRef );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+
+    /* Generate integer clip boundaries */
+    for( i=0; i<4; i++ ) {
+        clip_bounds[i] = (uint32_t)pvr2_scene.bounds[i];
+    }
+
+    setOrtho(viewMatrix, pvr2_scene.buffer_width, pvr2_scene.buffer_height, -farz, -nearz);
+
+    if( have_shaders ) {
+        pvr2_scene_setup_shader(viewMatrix);
+    } else {
+        pvr2_scene_setup_fixed(viewMatrix);
+    }
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
     /* Clear the buffer (FIXME: May not want always want to do this) */
     glDisable( GL_SCISSOR_TEST );
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -450,58 +550,85 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     glStencilMask( 0x03 );
     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    /* Setup vertex array pointers */
-    glVertexPointer(3, GL_FLOAT, sizeof(struct vertex_struct), &pvr2_scene.vertex_array[0].x);
-    glColorPointer(4, GL_FLOAT, sizeof(struct vertex_struct), &pvr2_scene.vertex_array[0].rgba[0]);
-    glTexCoordPointer(4, GL_FLOAT, sizeof(struct vertex_struct), &pvr2_scene.vertex_array[0].u);
-    glSecondaryColorPointerEXT(3, GL_FLOAT, sizeof(struct vertex_struct), pvr2_scene.vertex_array[0].offset_rgba );
-    glFogCoordPointerEXT(GL_FLOAT, sizeof(struct vertex_struct), &pvr2_scene.vertex_array[0].offset_rgba[3] );
-    /* Turn on the shaders (if available) */
-    glsl_use_pvr2_shader();
-
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     /* Render the background */
     gl_render_bkgnd( pvr2_scene.bkgnd_poly );
 
     glEnable( GL_SCISSOR_TEST );
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    glEnable( GL_COLOR_SUM );
-    glEnable( GL_FOG );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     glEnable( GL_TEXTURE_2D );
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    /* Process the segment list */
-    struct tile_segment *segment = pvr2_scene.segment_list;
-    do {
-        int tilex = SEGMENT_X(segment->control);
-        int tiley = SEGMENT_Y(segment->control);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    struct tile_segment *segment;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        uint32_t tile_bounds[4] = { tilex << 5, (tilex+1)<<5, tiley<<5, (tiley+1)<<5 };
-        if( !clip_tile_bounds(tile_bounds, pvr2_scene.bounds) ) {
-            continue; // fully clipped, skip tile
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#define FOREACH_SEGMENT(segment) \
+    segment = pvr2_scene.segment_list; \
+    do { \
+        int tilex = SEGMENT_X(segment->control); \
+        int tiley = SEGMENT_Y(segment->control); \
+        \
+        uint32_t tile_bounds[4] = { tilex << 5, (tilex+1)<<5, tiley<<5, (tiley+1)<<5 }; \
+        if( !clip_tile_bounds(tile_bounds, clip_bounds) ) { \
+            continue; \
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         }
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#define END_FOREACH_SEGMENT() \
+    } while( !IS_LAST_SEGMENT(segment++) );
+#define CLIP_TO_SEGMENT() \
+    glScissor( tile_bounds[0], pvr2_scene.buffer_height-tile_bounds[3], tile_bounds[1]-tile_bounds[0], tile_bounds[3] - tile_bounds[2] )
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        /* Clip to the visible part of the tile */
-        glScissor( tile_bounds[0], pvr2_scene.buffer_height-tile_bounds[3], 
-                   tile_bounds[1]-tile_bounds[0], tile_bounds[3] - tile_bounds[2] );
-        if( display_driver->capabilities.stencil_bits >= 2 && 
-                IS_TILE_PTR(segment->opaquemod_ptr) &&
-                !IS_EMPTY_TILE_LIST(segment->opaquemod_ptr) ) {
-            /* Don't do this unless there's actually some shadow polygons */
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    /* Build up the opaque stencil map */
+    if( display_driver->capabilities.stencil_bits >= 2 ) {
+        glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
+        FOREACH_SEGMENT(segment)
+            if( IS_NONEMPTY_TILE_LIST(segment->opaquemod_ptr) ) {
+                CLIP_TO_SEGMENT();
+                gl_render_tilelist_depthonly(segment->opaque_ptr);
+            }
+        END_FOREACH_SEGMENT()
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-            /* Use colormask instead of drawbuffer for simplicity */
-            glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
-            gl_render_tilelist_depthonly(segment->opaque_ptr);
-            gl_render_modifier_tilelist(segment->opaquemod_ptr, tile_bounds);
-            glClear( GL_DEPTH_BUFFER_BIT );
-            glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
-        }
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        glEnable( GL_STENCIL_TEST );
+        glStencilFunc( GL_ALWAYS, 0, 1 );
+        glStencilOp( GL_KEEP,GL_INVERT, GL_KEEP );
+        glStencilMask( 0x01 );
+        glDepthFunc( GL_LEQUAL );
+        glDepthMask( GL_FALSE );
+        glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
+        FOREACH_SEGMENT(segment)
+            if( IS_NONEMPTY_TILE_LIST(segment->opaquemod_ptr) ) {
+                CLIP_TO_SEGMENT();
+                gl_render_modifier_tilelist(segment->opaquemod_ptr, tile_bounds);
+            }
+        END_FOREACH_SEGMENT()
+        glDepthMask( GL_TRUE );
+        glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
+        glDisable( GL_SCISSOR_TEST );
+        glClear( GL_DEPTH_BUFFER_BIT );
+        glEnable( GL_SCISSOR_TEST );
+        glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
+    }
+
+    /* Render the opaque polygons */
+    FOREACH_SEGMENT(segment)
+        CLIP_TO_SEGMENT();
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         gl_render_tilelist(segment->opaque_ptr,TRUE);
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        if( IS_TILE_PTR(segment->punchout_ptr) ) {
-            glEnable(GL_ALPHA_TEST );
-            glDepthFunc(GL_GEQUAL);
-            gl_render_tilelist(segment->punchout_ptr, FALSE );
-            glDisable(GL_ALPHA_TEST );
-        }
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    END_FOREACH_SEGMENT()
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        if( IS_TILE_PTR(segment->trans_ptr) ) {
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    /* Render the punch-out polygons */
+    if( have_shaders )
+        pvr2_scene_set_alpha_shader(alphaRef);
+    else
+        pvr2_scene_set_alpha_fixed(alphaRef);
+    glDepthFunc(GL_GEQUAL);
+    FOREACH_SEGMENT(segment)
+        CLIP_TO_SEGMENT();
+        gl_render_tilelist(segment->punchout_ptr, FALSE );
+    END_FOREACH_SEGMENT()
+    if( have_shaders )
+        pvr2_scene_set_alpha_shader(0.0);
+    else
+        pvr2_scene_set_alpha_fixed(0.0);
+
+    /* Render the translucent polygons */
+    FOREACH_SEGMENT(segment)
+        if( IS_NONEMPTY_TILE_LIST(segment->trans_ptr) ) {
+            CLIP_TO_SEGMENT();
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             if( pvr2_scene.sort_mode == SORT_NEVER || 
                     (pvr2_scene.sort_mode == SORT_TILEFLAG && (segment->control&SEGMENT_SORT_TRANS))) {
                 gl_render_tilelist(segment->trans_ptr, TRUE);
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -509,11 +636,15 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >                 render_autosort_tile(segment->trans_ptr, RENDER_NORMAL );
             }
         }
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    } while( !IS_LAST_SEGMENT(segment++) );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    END_FOREACH_SEGMENT()
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     glDisable( GL_SCISSOR_TEST );
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    glDisable( GL_COLOR_SUM );
-    glDisable( GL_FOG );
-    glsl_clear_shader();
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+
+    if( have_shaders ) {
+        pvr2_scene_cleanup_shader();
+    } else {
+        pvr2_scene_cleanup_fixed();
+    }
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
     pvr2_scene_finished();
 
</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>shaders.glsl</b></big> <small id="info" style="color: #888888;" >d63c808ddcd3 -> e5b12e2fe6ba</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/pvr2/shaders.glsl
+++ lxdream/src/pvr2/shaders.glsl
@@ -66,44 +66,67 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 
 #vertex DEFAULT_VERTEX_SHADER
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+uniform mat4 view_matrix;
+attribute vec4 in_vertex;
+attribute vec4 in_colour;
+attribute vec4 in_colour2; /* rgb = colour, a = fog */
+attribute vec4 in_texcoord; /* uv = coord, z = palette, w = mode */
+
+varying vec4 frag_colour;
+varying vec4 frag_colour2;
+varying vec4 frag_texcoord;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > void main()
 {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    vec4 tmp = ftransform();
-    float w = gl_Vertex.z;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    vec4 tmp = view_matrix * in_vertex;
+    float w = in_vertex.z;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     gl_Position  = tmp * w;
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    gl_FrontColor = gl_Color;
-    gl_FrontSecondaryColor = gl_SecondaryColor;
-    gl_TexCoord[0] = gl_MultiTexCoord0;
-    gl_FogFragCoord = gl_FogCoord;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    frag_colour = in_colour;
+    frag_colour2 = in_colour2;
+    frag_texcoord = in_texcoord;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
 
 #fragment DEFAULT_FRAGMENT_SHADER
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+uniform float alpha_ref;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > uniform sampler2D primary_texture;
 uniform sampler2D palette_texture;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+uniform vec3 fog_colour1;
+uniform vec3 fog_colour2;
+varying vec4 frag_colour;
+varying vec4 frag_colour2;
+varying vec4 frag_texcoord;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 void main()
 {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-   vec4 tex = texture2D( primary_texture, gl_TexCoord[0].xy );
-       if( gl_TexCoord[0].z >= 0.0 ) {
-           tex = texture2D( palette_texture, vec2(gl_TexCoord[0].z + (tex.a*0.249023),0.5) );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+     vec4 tex = texture2D( primary_texture, frag_texcoord.xy );
+       if( frag_texcoord.z >= 0.0 ) {
+           tex = texture2D( palette_texture, vec2(frag_texcoord.z + (tex.a*0.249023), 0.5) );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >    }
        /* HACK: unfortunately we have to maintain compatibility with GLSL 1.20,
         * which only supports varying float. So since we're propagating texcoord
         * anyway, overload the last component to indicate texture mode. 
         */
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-   if( gl_TexCoord[0].w == 0.0 ) {
-           gl_FragColor.rgb = mix( gl_Color.rgb * tex.rgb + gl_SecondaryColor.rgb, gl_Fog.color.rgb, gl_FogFragCoord );
-           gl_FragColor.a = gl_Color.a * tex.a;
-       } else if( gl_TexCoord[0].w >= 1.5 ) {
-           gl_FragColor.rgb = mix( gl_Color.rgb, gl_Fog.color.rgb, gl_FogFragCoord );
-           gl_FragColor.a = gl_Color.a;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        vec3 main_colour;
+       if( frag_texcoord.w == 0.0 ) {
+            main_colour = frag_colour.rgb * tex.rgb + frag_colour2.rgb;
+           gl_FragColor.a = frag_colour.a * tex.a;
+       } else if( frag_texcoord.w >= 1.5 ) {
+            main_colour = frag_colour.rgb;
+           gl_FragColor.a = frag_colour.a;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >    } else {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-       gl_FragColor.rgb = mix( mix(gl_Color.rgb,tex.rgb,tex.a) + gl_SecondaryColor.rgb, gl_Fog.color.rgb, gl_FogFragCoord);
-           gl_FragColor.a = gl_Color.a;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+         main_colour =  mix(frag_colour.rgb,tex.rgb,tex.a) + frag_colour2.rgb;
+           gl_FragColor.a = frag_colour.a;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >    }
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-   gl_FragDepth = gl_FragCoord.z;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        if( gl_FragColor.a < alpha_ref ) {
+            discard;
+        } else { 
+           if( frag_colour2.a >= 0.0 ) {
+                gl_FragColor.rgb = mix( main_colour, fog_colour1, frag_colour2.a );
+            } else {
+                gl_FragColor.rgb = mix( main_colour, fog_colour2, -frag_colour2.a );
+            }
+           gl_FragDepth = gl_FragCoord.z;
+        } 
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
 
 #program pvr2_shader = DEFAULT_VERTEX_SHADER DEFAULT_FRAGMENT_SHADER
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-
</pre></div>
<center><small>Chaos Theory</small></center>
</div></body></html>