<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">gl_sl.c</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+42</td><td></td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">9af81878480b -> 7dc1c71ece76</td></tr>
<tr class="alt" style=";" ><td><tt><a href="#file2">glrender.c</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+16</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-4</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">9af81878480b -> 7dc1c71ece76</td></tr>
<tr><td><tt><a href="#file3">glutil.c</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+12</td><td></td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">9af81878480b -> 7dc1c71ece76</td></tr>
<tr class="alt" style=";" ><td><tt><a href="#file4">glutil.h</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+3</td><td></td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">9af81878480b -> 7dc1c71ece76</td></tr>
<tr><td><tt><a href="#file5">scene.c</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+33</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-8</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">9af81878480b -> 7dc1c71ece76</td></tr>
<tr class="alt" style=";" ><td><tt><a href="#file6">scene.h</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+1</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-1</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">9af81878480b -> 7dc1c71ece76</td></tr>
<tr><td><tt><a href="#file7">shaders.glsl</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+69</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">9af81878480b -> 7dc1c71ece76</td></tr>
<tr class="alt" style=";" ><td><tt><a href="#file8">texcache.c</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+206</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-58</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">9af81878480b -> 7dc1c71ece76</td></tr>
<tr><td></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+382</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-73</td><td></td></tr>
</table>
<small id="info" style="color: #888888;" >8 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;" >
Implement fragment shader to support palette textures 'directly', and
therefore avoid having to reload all palette textures whenever the palette
changes.
</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>gl_sl.c</b></big> <small id="info" style="color: #888888;" >9af81878480b -> 7dc1c71ece76</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/pvr2/gl_sl.c
+++ lxdream/src/pvr2/gl_sl.c
@@ -152,6 +152,16 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     glDeleteObjectARB(program);
 }
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static inline GLint glsl_get_uniform_location_prim(gl_program_t program, const char *name)
+{
+    return glGetUniformLocationARB(program, name);
+}
+
+static inline void glsl_set_uniform_int_prim(GLint location, GLint value)
+{
+    glUniform1iARB(location,value);
+}
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #elif HAVE_OPENGL_SHADER
 
 gboolean glsl_is_supported()
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -260,6 +270,15 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     glDeleteProgram(program);
 }
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static inline GLint glsl_get_uniform_location_prim(gl_program_t program, const char *name)
+{
+    return glGetUniformLocation(program, name);
+}
+static inline void glsl_set_uniform_int_prim(GLint location, GLint value)
+{
+    glUniform1i(location, value);
+}
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #else
 gboolean glsl_is_supported()
 {
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -297,6 +316,15 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > void glsl_destroy_program(gl_program_t program)
 {
 }
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+
+static inline GLint glsl_get_uniform_location_prim(gl_program_t program, const char *name)
+{
+    return 0;
+}
+
+static inline void glsl_set_uniform_int_prim(GLint location, GLint value)
+{
+}
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #endif
 
 /****************************************************************************/
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -394,6 +422,20 @@
</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;" >+GLint glsl_get_uniform_location( unsigned program, const char *name )
+{
+    assert( program >= 0 && program <= GLSL_LAST_PROGRAM );
+
+    return glsl_get_uniform_location_prim(program_array[program], name);
+}
+
+void glsl_set_uniform_int( unsigned program, const char *name, GLint value )
+{
+    assert( program >= 0 && program <= GLSL_LAST_PROGRAM );
+    GLint location = glsl_get_uniform_location_prim(program_array[program], name);
+    glsl_set_uniform_int_prim(location, value);
+}
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > void glsl_clear_shader()
 {
     glsl_use_program(0);
</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>glrender.c</b></big> <small id="info" style="color: #888888;" >9af81878480b -> 7dc1c71ece76</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/pvr2/glrender.c
+++ lxdream/src/pvr2/glrender.c
@@ -44,6 +44,8 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         GL_MODULATE 
 };
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static gboolean have_shaders = FALSE;
+
</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 class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -83,16 +85,17 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
 
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > /**
  * Once-off call to setup the OpenGL context.
  */
 void pvr2_setup_gl_context()
 {
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    if( glsl_is_supported() ) {
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    if( glsl_is_supported() && isGLMultitextureSupported() ) {
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         if( !glsl_load_shaders( ) ) {
             WARN( "Unable to load GL shaders" );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        } else {
+            have_shaders = TRUE;
</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;" >@@ -125,6 +128,13 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     glFogi(GL_FOG_MODE, GL_LINEAR);
     glFogf(GL_FOG_START, 0.0);
     glFogf(GL_FOG_END, 1.0);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+
+    if( have_shaders ) {
+        glsl_set_shader(DEFAULT_PROGRAM);
+        glsl_set_uniform_int(DEFAULT_PROGRAM, "primary_texture", 0);
+        glsl_set_uniform_int(DEFAULT_PROGRAM, "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;" >@@ -146,11 +156,13 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > void render_set_tsp_context( uint32_t poly1, uint32_t poly2 )
 {
     glShadeModel( POLY1_SHADE_MODEL(poly1) );
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    if( POLY1_TEXTURED(poly1) ) {
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+
+    if( POLY1_TEXTURED(poly1) && !have_shaders ) {
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         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;" >      }
 
      switch( POLY2_FOG_MODE(poly2) ) {
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -482,7 +494,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     /* 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]);
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    glTexCoordPointer(<span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >2</span>, GL_FLOAT, sizeof(struct vertex_struct), &pvr2_scene.vertex_array[0].u);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    glTexCoordPointer(<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >4</span>, GL_FLOAT, sizeof(struct vertex_struct), &pvr2_scene.vertex_array[0].u);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     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) */
</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>glutil.c</b></big> <small id="info" style="color: #888888;" >9af81878480b -> 7dc1c71ece76</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/pvr2/glutil.c
+++ lxdream/src/pvr2/glutil.c
@@ -41,6 +41,18 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     return isGLExtensionSupported("GL_ARB_texture_mirrored_repeat");
 }
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+/**
+ * Check if there's at least 2 texture units
+ */
+gboolean isGLMultitextureSupported()
+{
+    if( !isGLExtensionSupported("GL_ARB_multitexture") )
+        return FALSE;
+    int units = 0;
+    glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &units);
+    return units >= 2;
+}
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > gboolean isGLVertexRangeSupported()
 {
     return isGLExtensionSupported("GL_APPLE_vertex_array_range") ||
</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>glutil.h</b></big> <small id="info" style="color: #888888;" >9af81878480b -> 7dc1c71ece76</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/pvr2/glutil.h
+++ lxdream/src/pvr2/glutil.h
@@ -47,6 +47,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > gboolean isGLVertexBufferSupported();
 gboolean isGLVertexRangeSupported();
 gboolean isGLPixelBufferSupported();
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+gboolean isGLMultitextureSupported();
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > gboolean isGLMirroredTextureSupported();
 
 /****** Shader handling (gl_sl.c) *****/
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -56,6 +57,8 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > void glsl_unload_shaders(void);
 gboolean glsl_set_shader( unsigned program_id );
 void glsl_clear_shader();
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+GLint glsl_get_uniform_location( unsigned program, const char *name );
+void glsl_set_uniform_int( unsigned program, const char *name, GLint value );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 /* Convenience formatting function for driver use */
 void fprint_extensions( FILE *out, const char *extensions );
</pre></div>
<hr /><a name="file5" /><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;" >9af81878480b -> 7dc1c71ece76</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/pvr2/scene.c
+++ lxdream/src/pvr2/scene.c
@@ -226,6 +226,18 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     return poly;
 }
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static float scene_get_palette_offset( uint32_t tex )
+{
+    uint32_t fmt = (tex & PVR2_TEX_FORMAT_MASK);
+    if( fmt == PVR2_TEX_FORMAT_IDX4 ) {
+        return ((float)((tex & 0x07E00000) >> 17))/1024.0 + 0.0002;
+    } else if( fmt == PVR2_TEX_FORMAT_IDX8 ) {
+        return ((float)((tex & 0x06000000) >> 17))/1024.0 + 0.0002;
+    } else {
+        return -1.0;
+    }
+}
+
</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)
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -237,7 +249,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  *        the normal vertex, half the vertex length for the modified vertex.
  */
 static void pvr2_decode_render_vertex( struct vertex_struct *vert, uint32_t poly1,
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-                                       uint32_t poly2, uint32_t *pvr2_data,
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+                                       uint32_t poly2, uint32_t <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >tex, uint32_t </span>*pvr2_data,
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >                                        int modify_offset )
 {
     gboolean force_alpha = !POLY2_ALPHA_ENABLE(poly2);
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -279,16 +291,25 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         switch( POLY2_TEX_BLEND(poly2) ) {
         case 0:/* Convert replace => modulate by setting colour values to 1.0 */
             vert->rgba[0] = vert->rgba[1] = vert->rgba[2] = vert->rgba[3] = 1.0;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+            vert->tex_mode = 0.0;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             data.ival++; /* Skip the colour word */
             break;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        case 2: /* Decal */
+            vert->tex_mode = 1.0;
+            unpack_bgra(*data.ival++, vert->rgba);
+            break;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         case 1:
             force_alpha = TRUE;
             /* fall-through */
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        default: /* Can't handle decal this way */
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        default:
+            vert->tex_mode = 0.0;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             unpack_bgra(*data.ival++, vert->rgba);
             break;
         }
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        vert->r = scene_get_palette_offset(tex);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     } else {
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        vert->tex_mode = 2.0;
+        vert->r = -1.0;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         unpack_bgra(*data.ival++, vert->rgba);
     }
 
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -357,6 +378,8 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         result[i].z = rz;
         result[i].u = input[1].u + (t*tu) + (s*su);
         result[i].v = input[1].v + (t*tv) + (s*sv);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        result[i].r = input[1].r; /* Last two components are flat */
+        result[i].tex_mode = input[1].tex_mode;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
         if( is_solid_shaded ) {
             memcpy( result->rgba, input[2].rgba, sizeof(result->rgba) );
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -503,6 +526,8 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         dest->z = src->z;
         dest->u = src->u;
         dest->v = src->v;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        dest->r = src->r;
+        dest->tex_mode = src->tex_mode;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         dest->rgba[0] = src->rgba[0] * scene_shadow_intensity;
         dest->rgba[1] = src->rgba[1] * scene_shadow_intensity;
         dest->rgba[2] = src->rgba[2] * scene_shadow_intensity;
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -531,7 +556,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         assert( poly != NULL );
         assert( pvr2_scene.vertex_index + poly->vertex_count <= pvr2_scene.vertex_count );
         for( i=0; i<poly->vertex_count; i++ ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-            pvr2_decode_render_vertex( &pvr2_scene.vertex_array[pvr2_scene.vertex_index++], context[0], context[1], ptr, 0 );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+            pvr2_decode_render_vertex( &pvr2_scene.vertex_array[pvr2_scene.vertex_index++], context[0], context[1], <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >context[2], </span>ptr, 0 );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             ptr += vertex_length;
         }
         if( is_modified ) {
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -541,7 +566,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >                 int mod_offset = (vertex_length - 3)>>1;
                 ptr = &pvr2_scene.pvr2_pbuf[poly_idx] + 5;
                 for( i=0; i<poly->vertex_count; i++ ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-                    pvr2_decode_render_vertex( &pvr2_scene.vertex_array[pvr2_scene.vertex_index++], context[0], context[3], ptr, mod_offset );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+                    pvr2_decode_render_vertex( &pvr2_scene.vertex_array[pvr2_scene.vertex_index++], context[0], context[3], <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >context[4], </span>ptr, mod_offset );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >                     ptr += vertex_length;
                 }
             } else {
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -572,7 +597,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         ptr += (is_modified == SHADOW_FULL ? 5 : 3 );
         poly->vertex_index = pvr2_scene.vertex_index;
         for( i=0; i<4; i++ ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-            pvr2_decode_render_vertex( &quad[i], context[0], context[1], ptr, 0 );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+            pvr2_decode_render_vertex( &quad[i], context[0], context[1], <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >context[2], </span>ptr, 0 );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             ptr += vertex_length;
         }
         scene_compute_vertexes( &quad[3], 1, &quad[0], !POLY1_GOURAUD_SHADED(context[0]) );
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -589,7 +614,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >                 int mod_offset = (vertex_length - 3)>>1;
                 ptr = &pvr2_scene.pvr2_pbuf[poly_idx] + 5;
                 for( i=0; i<4; i++ ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-                    pvr2_decode_render_vertex( &quad[4], context[0], context[3], ptr, mod_offset );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+                    pvr2_decode_render_vertex( &quad[4], context[0], context[3], <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >context[4], </span>ptr, mod_offset );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >                     ptr += vertex_length;
                 }
                 scene_compute_vertexes( &quad[3], 1, &quad[0], !POLY1_GOURAUD_SHADED(context[0]) );
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -759,7 +784,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     struct vertex_struct base_vertexes[3];
     uint32_t *ptr = context + context_length;
     for( i=0; i<3; i++ ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        pvr2_decode_render_vertex( &base_vertexes[i], context[0], context[1],
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        pvr2_decode_render_vertex( &base_vertexes[i], context[0], context[1],<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" > context[2],</span>
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >                 ptr, 0 );
         ptr += vertex_length;
     }
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -774,7 +799,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         int mod_offset = (vertex_length - 3)>>1;
         ptr = context + context_length;
         for( i=0; i<3; i++ ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-            pvr2_decode_render_vertex( &base_vertexes[i], context[0], context[3],
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+            pvr2_decode_render_vertex( &base_vertexes[i], context[0], context[3],<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" > context[4],</span>
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >                     ptr, mod_offset );
             ptr += vertex_length;
         }
</pre></div>
<hr /><a name="file6" /><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;" >9af81878480b -> 7dc1c71ece76</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/pvr2/scene.h
+++ lxdream/src/pvr2/scene.h
@@ -35,7 +35,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 
 struct vertex_struct {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    float u,v;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    float u,v,r,tex_mode; /* tex-coord quad */
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     float x,y,z;
     float rgba[4];
     float offset_rgba[4];
</pre></div>
<hr /><a name="file7" /><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;" >9af81878480b -> 7dc1c71ece76</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/pvr2/shaders.glsl
+++ lxdream/src/pvr2/shaders.glsl
@@ -19,6 +19,52 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  * GNU General Public License for more details.
  */
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+/**
+ * Quick reference for predefined variables

+ * Vertex shader input variables:
+ *   vec4 gl_Color;
+ *   vec4 gl_SecondaryColor;
+ *   vec3 gl_Normal;
+ *   vec4 gl_Vertex;
+ *   vec4 gl_MultiTexCoord0;
+ *   vec4 gl_MultiTexCoord1; 
+ *   vec4 gl_MultiTexCoord2;
+ *   vec4 gl_MultiTexCoord3; 
+ *   vec4 gl_MultiTexCoord4;
+ *   vec4 gl_MultiTexCoord5;
+ *   vec4 gl_MultiTexCoord6;
+ *   vec4 gl_MultiTexCoord7;
+ *   float gl_FogCoord;
+ *
+ * Vertex shader output variables:
+ *   vec4 gl_Position;    // must be written to
+ *   float gl_PointSize;  // may be written to
+ *   vec4 gl_ClipVertex;  // may be written to
+ *   varying vec4 gl_FrontColor; 
+ *   varying vec4 gl_BackColor; 
+ *   varying vec4 gl_FrontSecondaryColor; 
+ *   varying vec4 gl_BackSecondaryColor; 
+ *   varying vec4 gl_TexCoord[]; // at most will be gl_MaxTextureCoords
+ *   varying float gl_FogFragCoord;
+ *
+ * Fragment shader input variables:
+ *   varying vec4 gl_Color; 
+ *   varying vec4 gl_SecondaryColor; 
+ *   varying vec4 gl_TexCoord[]; // at most will be gl_MaxTextureCoords
+ *   varying float gl_FogFragCoord;
+ *   varying vec2 gl_PointCoord;
+ *
+ * Fragme shader output variables:
+ *   vec4 gl_FragCoord; 
+ *   bool gl_FrontFacing; 
+ *   vec4 gl_FragColor; 
+ *   vec4 gl_FragData[gl_MaxDrawBuffers]; 
+ *   float gl_FragDepth;
+
+ */
+
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #vertex DEFAULT_VERTEX_SHADER
 void main()
 {
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -32,11 +78,32 @@
</small></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 sampler2D primary_texture;
+uniform sampler1D palette_texture;
+
</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;" >-   gl_FragColor = gl_Color;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+     vec4 tex = texture2D( primary_texture, gl_TexCoord[0].xy );
+       if( gl_TexCoord[0].z >= 0.0 ) {
+           tex = texture1D( palette_texture, gl_TexCoord[0].z + (tex.a*0.249023) );
+       }
+       /* 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. 
+        */
+       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;
+       } else {
+           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="context" class="diff" style="margin:0; background-color:#eeeeee;" >    gl_FragDepth = gl_FragCoord.z;
 }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-#program DEFAULT_PROGRAM = DEFAULT_VERTEX_SHADER
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#program DEFAULT_PROGRAM = DEFAULT_VERTEX_SHADER<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" > DEFAULT_FRAGMENT_SHADER</span>
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
</pre></div>
<hr /><a name="file8" /><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>texcache.c</b></big> <small id="info" style="color: #888888;" >9af81878480b -> 7dc1c71ece76</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/pvr2/texcache.c
+++ lxdream/src/pvr2/texcache.c
@@ -22,6 +22,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #include <string.h>
 #include "pvr2/pvr2.h"
 #include "pvr2/pvr2mmio.h"
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#include "pvr2/glutil.h"
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 /** Specifies the maximum number of OpenGL
  * textures we're willing to have open at a time. If more are
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -59,6 +60,9 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > static struct texcache_entry texcache_active_list[MAX_TEXTURES];
 static uint32_t texcache_palette_mode;
 static uint32_t texcache_stride_width;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static gboolean texcache_have_palette_shader;
+static gboolean texcache_palette_valid;
+static GLuint texcache_palette_texid;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 /**
  * Initialize the texture cache.
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -77,7 +81,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
     texcache_free_ptr = 0;
     texcache_ref_counter = 0;
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    texcache_palette_mode = <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >0</span>;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    texcache_palette_mode = <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >-1</span>;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     texcache_stride_width = 0;
 }
 
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -90,6 +94,23 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     int i;
     GLuint texids[MAX_TEXTURES];
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    if( glsl_is_supported() && isGLMultitextureSupported ) {
+        texcache_have_palette_shader = TRUE;
+        texcache_palette_valid = FALSE;
+        glGenTextures(1, &texcache_palette_texid );
+
+        /* Bind the texture and set the params */
+        glActiveTexture(GL_TEXTURE1);
+        glBindTexture(GL_TEXTURE_1D, texcache_palette_texid);
+        glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP );
+        glActiveTexture(GL_TEXTURE0);
+
+    } else {
+        texcache_have_palette_shader = FALSE;
+    }
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     glGenTextures( MAX_TEXTURES, texids );
     for( i=0; i<MAX_TEXTURES; i++ ) {
         texcache_active_list[i].texture_id = texids[i];
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -137,6 +158,9 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     int i;
     texcache_flush();
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    if( texcache_have_palette_shader )
+        glDeleteTextures( 1, &texcache_palette_texid );
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     for( i=0; i<MAX_TEXTURES; i++ ) {
         texids[i] = texcache_active_list[i].texture_id;
     }
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -220,20 +244,83 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
 
 /**
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >- * Mark all textures that use the palette table as needing a re-read (ie 
- * for when the palette is changed. We could track exactly which ones are 
- * affected, but it's not clear that the extra maintanence overhead is 
- * worthwhile.
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ * Load the palette into 4 textures of 256 entries each. This mirrors the
+ * banking done by the PVR2 for 8-bit textures, and also ensures that we
+ * can use 8-bit paletted textures ourselves.
+ */
+static void texcache_load_palette_texture( gboolean format_changed )
+{
+    GLint format, type, intFormat = GL_RGBA;
+    unsigned i;
+    int bpp = 2;
+    uint32_t *palette = (uint32_t *)mmio_region_PVR2PAL.mem;
+    uint16_t packed_palette[1024];
+    char *data = (char *)palette;
+
+    switch( texcache_palette_mode ) {
+    case 0: /* ARGB1555 */
+        format = GL_BGRA;
+        type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
+        break;
+    case 1:  /* RGB565 */
+        intFormat = GL_RGB;
+        format = GL_RGB;
+        type = GL_UNSIGNED_SHORT_5_6_5;
+        break;
+    case 2: /* ARGB4444 */
+        format = GL_BGRA;
+        type = GL_UNSIGNED_SHORT_4_4_4_4_REV;
+        break;
+    case 3: /* ARGB8888 */
+        format = GL_BGRA;
+        type = GL_UNSIGNED_BYTE;
+        bpp = 4;
+        break;
+    default:
+        break; /* Can't happen */
+    }
+
+
+    if( bpp == 2 ) {
+        for( i=0; i<1024; i++ ) {
+            packed_palette[i] = (uint16_t)palette[i];
+        }
+        data = (char *)packed_palette;
+
+    }
+
+    glActiveTexture(GL_TEXTURE1);
+//    glBindTexture(GL_TEXTURE_1D, texcache_palette_texid);
+    if( format_changed )
+        glTexImage1D(GL_TEXTURE_1D, 0, intFormat, 1024, 0, format, type, data );
+    else
+        glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 1024, format, type, data);
+//    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+//    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+//    glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP );
+    glActiveTexture(GL_TEXTURE0);
+    texcache_palette_valid = TRUE;
+}
+
+
+/**
+ * Mark the palette as having changed. If we have palette support (via shaders)
+ * we just flag the palette, otherwise we have to invalidate all palette
+ * textures.
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  */
 void texcache_invalidate_palette( )
 {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    int i;
-    for( i=0; i<MAX_TEXTURES; i++ ) {
-        if( texcache_active_list[i].texture_addr != -1 &&
-                PVR2_TEX_IS_PALETTE(texcache_active_list[i].tex_mode) ) {
-            texcache_evict( i );
-            texcache_free_ptr--;
-            texcache_free_list[texcache_free_ptr] = i;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    if( texcache_have_palette_shader ) {
+        texcache_palette_valid = FALSE;
+    } else {
+        int i;
+        for( i=0; i<MAX_TEXTURES; i++ ) {
+            if( texcache_active_list[i].texture_addr != -1 &&
+                    PVR2_TEX_IS_PALETTE(texcache_active_list[i].tex_mode) ) {
+                texcache_evict( i );
+                texcache_free_ptr--;
+                texcache_free_list[texcache_free_ptr] = i;
+            }
</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;" >@@ -256,13 +343,19 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 void texcache_begin_scene( uint32_t palette_mode, uint32_t stride )
 {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    if( palette_mode != texcache_palette_mode )
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    gboolean format_changed = FALSE;
+    if( palette_mode != texcache_palette_mode ) {
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         texcache_invalidate_palette();
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        format_changed = TRUE;
+    }
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     if( stride != texcache_stride_width )
         texcache_invalidate_stride();
     
     texcache_palette_mode = palette_mode;
     texcache_stride_width = stride;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+
+    if( !texcache_palette_valid && texcache_have_palette_shader )
+        texcache_load_palette_texture(format_changed);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
 
 static void decode_pal8_to_32( uint32_t *out, uint8_t *in, int inbytes, uint32_t *pal )
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -291,6 +384,17 @@
</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;" >+static void decode_pal4_to_pal8( uint8_t *out, uint8_t *in, int inbytes )
+{
+    int i;
+    for( i=0; i<inbytes; i++ ) {
+        *out++ = (uint8_t)(*in & 0x0F);
+        *out++ = (uint8_t)(*in >> 4);
+        in++;
+    }
+}
+
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 static void decode_pal4_to_16( uint16_t *out, uint8_t *in, int inbytes, uint32_t *pal )
 {
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -395,7 +499,9 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     GLint intFormat = GL_RGBA, format, type;
     int tex_format = mode & PVR2_TEX_FORMAT_MASK;
     struct vq_codebook codebook;
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    GLint filter = GL_LINEAR;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    GLint <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >min_</span>filter = GL_LINEAR;
+    GLint max_filter = GL_LINEAR;
+    GLint mipmapfilter = GL_LINEAR_MIPMAP_LINEAR;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
     glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
 
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -403,30 +509,39 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     switch( tex_format ) {
     case PVR2_TEX_FORMAT_IDX4:
     case PVR2_TEX_FORMAT_IDX8:
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        /* For indexed-colour modes, we need to lookup the palette control
-         * word to determine the de-indexed texture format.
-         */
-        switch( texcache_palette_mode ) {
-        case 0: /* ARGB1555 */
-            format = GL_BGRA;
-            type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
-            break;
-        case 1:  /* RGB565 */
-            intFormat = GL_RGB;
-            format = GL_RGB;
-            type = GL_UNSIGNED_SHORT_5_6_5;
-            break;
-        case 2: /* ARGB4444 */
-            format = GL_BGRA;
-            type = GL_UNSIGNED_SHORT_4_4_4_4_REV;
-            break;
-        case 3: /* ARGB8888 */
-            format = GL_BGRA;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        if( texcache_have_palette_shader ) {
+            intFormat = GL_ALPHA8;
+            format = GL_ALPHA;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             type = GL_UNSIGNED_BYTE;
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-            bpp_shift = 2;
-            break;
-        default:
-            return; /* Can't happen, but it makes gcc stop complaining */
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+            bpp_shift = 0;
+            min_filter = max_filter = GL_NEAREST;
+            mipmapfilter = GL_NEAREST_MIPMAP_NEAREST;
+        } else {
+            /* For indexed-colour modes, we need to lookup the palette control
+             * word to determine the de-indexed texture format.
+             */
+            switch( texcache_palette_mode ) {
+            case 0: /* ARGB1555 */
+                format = GL_BGRA;
+                type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
+                break;
+            case 1:  /* RGB565 */
+                intFormat = GL_RGB;
+                format = GL_RGB;
+                type = GL_UNSIGNED_SHORT_5_6_5;
+                break;
+            case 2: /* ARGB4444 */
+                format = GL_BGRA;
+                type = GL_UNSIGNED_SHORT_4_4_4_4_REV;
+                break;
+            case 3: /* ARGB8888 */
+                format = GL_BGRA;
+                type = GL_UNSIGNED_BYTE;
+                bpp_shift = 2;
+                break;
+            default:
+                return; /* Can't happen, but it makes gcc stop complaining */
+            }
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         }
         break;
 
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -469,8 +584,8 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             pvr2_vram64_read_stride( data, width<<bpp_shift, texture_addr, texcache_stride_width<<bpp_shift, height );
         }
         glTexImage2D( GL_TEXTURE_2D, 0, intFormat, width, height, 0, format, type, data );
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, max_filter);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         return;
     } 
 
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -484,7 +599,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     int level=0, last_level = 0, mip_width = width, mip_height = height, src_bytes, dest_bytes;
     if( PVR2_TEX_IS_MIPMAPPED(mode) ) {
         uint32_t src_offset = 0;
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        filter = GL_LINEAR_MIPMAP_LINEAR;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        min_filter = mipmapfilter;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         mip_height = height = width;
         while( (1<<last_level) < width ) {
             last_level++;
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -513,26 +628,35 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         unsigned char data[dest_bytes];
         /* load data from image, detwiddling/uncompressing as required */
         if( tex_format == PVR2_TEX_FORMAT_IDX8 ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-            src_bytes = (mip_width * mip_height);
-            int bank = (mode >> 25) &0x03;
-            uint32_t *palette = ((uint32_t *)mmio_region_PVR2PAL.mem) + (bank<<8);
-            unsigned char tmp[src_bytes];
-            pvr2_vram64_read_twiddled_8( tmp, texture_addr, mip_width, mip_height );
-            if( bpp_shift == 2 ) {
-                decode_pal8_to_32( (uint32_t *)data, tmp, src_bytes, palette );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+            if( texcache_have_palette_shader ) {
+                pvr2_vram64_read_twiddled_8( data, texture_addr, mip_width, mip_height );
</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;" >-                decode_pal8_to_16( (uint16_t *)data, tmp, src_bytes, palette );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+                src_bytes = (mip_width * mip_height);
+                int bank = (mode >> 25) &0x03;
+                uint32_t *palette = ((uint32_t *)mmio_region_PVR2PAL.mem) + (bank<<8);
+                unsigned char tmp[src_bytes];
+                pvr2_vram64_read_twiddled_8( tmp, texture_addr, mip_width, mip_height );
+                if( bpp_shift == 2 ) {
+                    decode_pal8_to_32( (uint32_t *)data, tmp, src_bytes, palette );
+                } else {
+                    decode_pal8_to_16( (uint16_t *)data, tmp, src_bytes, palette );
+                }
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             }
         } else if( tex_format == PVR2_TEX_FORMAT_IDX4 ) {
             src_bytes = (mip_width * mip_height) >> 1;
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-            int bank = (mode >>21 ) & 0x3F;
-            uint32_t *palette = ((uint32_t *)mmio_region_PVR2PAL.mem) + (bank<<4);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             unsigned char tmp[src_bytes];
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-            pvr2_vram64_read_twiddled_4( tmp, texture_addr, mip_width, mip_height );
-            if( bpp_shift == 2 ) {
-                decode_pal4_to_32( (uint32_t *)data, tmp, src_bytes, palette );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+            if( texcache_have_palette_shader ) {
+                pvr2_vram64_read_twiddled_4( tmp, texture_addr, mip_width, mip_height );
+                decode_pal4_to_pal8( data, tmp, src_bytes );
</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;" >-                decode_pal4_to_16( (uint16_t *)data, tmp, src_bytes, palette );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+                int bank = (mode >>21 ) & 0x3F;
+                uint32_t *palette = ((uint32_t *)mmio_region_PVR2PAL.mem) + (bank<<4);
+                pvr2_vram64_read_twiddled_4( tmp, texture_addr, mip_width, mip_height );
+                if( bpp_shift == 2 ) {
+                    decode_pal4_to_32( (uint32_t *)data, tmp, src_bytes, palette );
+                } else {
+                    decode_pal4_to_16( (uint16_t *)data, tmp, src_bytes, palette );
+                }
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             }
         } else if( tex_format == PVR2_TEX_FORMAT_YUV422 ) {
             src_bytes = ((mip_width*mip_height)<<1);
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -575,8 +699,8 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         }
     }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, max_filter);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
 
 static int texcache_find_texture_slot( uint32_t poly2_masked_word, uint32_t texture_word )
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -646,11 +770,15 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > GLuint texcache_get_texture( uint32_t poly2_word, uint32_t texture_word )
 {
     poly2_word &= 0x000F803F; /* Get just the texture-relevant bits */
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    int slot = texcache_find_texture_slot( poly2_word, texture_word );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    uint32_t texture_lookup = texture_word;
+    if( PVR2_TEX_IS_PALETTE(texture_lookup) ) {
+        texture_lookup &= 0xF81FFFFF; /* Mask out the bank bits */
+    }
+    int slot = texcache_find_texture_slot( poly2_word, texture_lookup );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
     if( slot == -1 ) {
         /* Not found - check the free list */
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        slot = texcache_alloc_texture_slot( poly2_word, texture_<span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >word</span> );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        slot = texcache_alloc_texture_slot( poly2_word, texture_<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >lookup</span> );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         
         /* Construct the GL texture */
         uint32_t texture_addr = (texture_word & 0x000FFFFF)<<3;
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -750,3 +878,23 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         assert( slot_found[i] != 0 );
     }
 }
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+
+/**
+ * Dump the contents of the texture cache
+ */
+void texcache_dump()
+{
+    unsigned i;
+    for( i=0; i< PVR2_RAM_PAGES; i++ ) {
+        int slot = texcache_page_lookup[i];
+        while( slot != EMPTY_ENTRY ) {
+            fprintf( stderr, "%-3d: %08X %dx%d (%08X %08X)\n", slot,
+                    texcache_active_list[slot].texture_addr,
+                    POLY2_TEX_WIDTH(texcache_active_list[slot].poly2_mode),
+                    POLY2_TEX_HEIGHT(texcache_active_list[slot].poly2_mode),
+                    texcache_active_list[slot].poly2_mode,
+                    texcache_active_list[slot].tex_mode );
+            slot = texcache_active_list[slot].next;
+        }
+    }
+}
</pre></div>
<center><small>Chaos Theory</small></center>
</div></body></html>