revision 1140:7dc1c71ece76
summary |
tree |
shortlog |
changelog |
graph |
changeset |
raw | bz2 | zip | gz changeset | 1140:7dc1c71ece76 |
parent | 1139:9af81878480b |
child | 1141:dc60a0987db9 |
author | nkeynes |
date | Tue Oct 26 08:39:02 2010 +1000 (13 years ago) |
Implement fragment shader to support palette textures 'directly', and
therefore avoid having to reload all palette textures whenever the palette
changes.
therefore avoid having to reload all palette textures whenever the palette
changes.
1.1 --- a/src/pvr2/gl_sl.c Sun Oct 24 15:22:59 2010 +10001.2 +++ b/src/pvr2/gl_sl.c Tue Oct 26 08:39:02 2010 +10001.3 @@ -152,6 +152,16 @@1.4 glDeleteObjectARB(program);1.5 }1.7 +static inline GLint glsl_get_uniform_location_prim(gl_program_t program, const char *name)1.8 +{1.9 + return glGetUniformLocationARB(program, name);1.10 +}1.11 +1.12 +static inline void glsl_set_uniform_int_prim(GLint location, GLint value)1.13 +{1.14 + glUniform1iARB(location,value);1.15 +}1.16 +1.17 #elif HAVE_OPENGL_SHADER1.19 gboolean glsl_is_supported()1.20 @@ -260,6 +270,15 @@1.21 glDeleteProgram(program);1.22 }1.24 +static inline GLint glsl_get_uniform_location_prim(gl_program_t program, const char *name)1.25 +{1.26 + return glGetUniformLocation(program, name);1.27 +}1.28 +static inline void glsl_set_uniform_int_prim(GLint location, GLint value)1.29 +{1.30 + glUniform1i(location, value);1.31 +}1.32 +1.33 #else1.34 gboolean glsl_is_supported()1.35 {1.36 @@ -297,6 +316,15 @@1.37 void glsl_destroy_program(gl_program_t program)1.38 {1.39 }1.40 +1.41 +static inline GLint glsl_get_uniform_location_prim(gl_program_t program, const char *name)1.42 +{1.43 + return 0;1.44 +}1.45 +1.46 +static inline void glsl_set_uniform_int_prim(GLint location, GLint value)1.47 +{1.48 +}1.49 #endif1.51 /****************************************************************************/1.52 @@ -394,6 +422,20 @@1.53 }1.54 }1.56 +GLint glsl_get_uniform_location( unsigned program, const char *name )1.57 +{1.58 + assert( program >= 0 && program <= GLSL_LAST_PROGRAM );1.59 +1.60 + return glsl_get_uniform_location_prim(program_array[program], name);1.61 +}1.62 +1.63 +void glsl_set_uniform_int( unsigned program, const char *name, GLint value )1.64 +{1.65 + assert( program >= 0 && program <= GLSL_LAST_PROGRAM );1.66 + GLint location = glsl_get_uniform_location_prim(program_array[program], name);1.67 + glsl_set_uniform_int_prim(location, value);1.68 +}1.69 +1.70 void glsl_clear_shader()1.71 {1.72 glsl_use_program(0);
2.1 --- a/src/pvr2/glrender.c Sun Oct 24 15:22:59 2010 +10002.2 +++ b/src/pvr2/glrender.c Tue Oct 26 08:39:02 2010 +10002.3 @@ -44,6 +44,8 @@2.4 GL_MODULATE2.5 };2.7 +static gboolean have_shaders = FALSE;2.8 +2.9 /**2.10 * Clip the tile bounds to the clipping plane.2.11 * @return TRUE if the tile was not clipped completely.2.12 @@ -83,16 +85,17 @@2.13 }2.16 -2.17 /**2.18 * Once-off call to setup the OpenGL context.2.19 */2.20 void pvr2_setup_gl_context()2.21 {2.23 - if( glsl_is_supported() ) {2.24 + if( glsl_is_supported() && isGLMultitextureSupported() ) {2.25 if( !glsl_load_shaders( ) ) {2.26 WARN( "Unable to load GL shaders" );2.27 + } else {2.28 + have_shaders = TRUE;2.29 }2.30 }2.32 @@ -125,6 +128,13 @@2.33 glFogi(GL_FOG_MODE, GL_LINEAR);2.34 glFogf(GL_FOG_START, 0.0);2.35 glFogf(GL_FOG_END, 1.0);2.36 +2.37 + if( have_shaders ) {2.38 + glsl_set_shader(DEFAULT_PROGRAM);2.39 + glsl_set_uniform_int(DEFAULT_PROGRAM, "primary_texture", 0);2.40 + glsl_set_uniform_int(DEFAULT_PROGRAM, "palette_texture", 1);2.41 + glsl_clear_shader();2.42 + }2.43 }2.45 /**2.46 @@ -146,11 +156,13 @@2.47 void render_set_tsp_context( uint32_t poly1, uint32_t poly2 )2.48 {2.49 glShadeModel( POLY1_SHADE_MODEL(poly1) );2.50 - if( POLY1_TEXTURED(poly1) ) {2.51 +2.52 + if( POLY1_TEXTURED(poly1) && !have_shaders ) {2.53 if( POLY2_TEX_BLEND(poly2) == 2 )2.54 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );2.55 else2.56 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );2.57 +2.58 }2.60 switch( POLY2_FOG_MODE(poly2) ) {2.61 @@ -482,7 +494,7 @@2.62 /* Setup vertex array pointers */2.63 glVertexPointer(3, GL_FLOAT, sizeof(struct vertex_struct), &pvr2_scene.vertex_array[0].x);2.64 glColorPointer(4, GL_FLOAT, sizeof(struct vertex_struct), &pvr2_scene.vertex_array[0].rgba[0]);2.65 - glTexCoordPointer(2, GL_FLOAT, sizeof(struct vertex_struct), &pvr2_scene.vertex_array[0].u);2.66 + glTexCoordPointer(4, GL_FLOAT, sizeof(struct vertex_struct), &pvr2_scene.vertex_array[0].u);2.67 glSecondaryColorPointerEXT(3, GL_FLOAT, sizeof(struct vertex_struct), pvr2_scene.vertex_array[0].offset_rgba );2.68 glFogCoordPointerEXT(GL_FLOAT, sizeof(struct vertex_struct), &pvr2_scene.vertex_array[0].offset_rgba[3] );2.69 /* Turn on the shaders (if available) */
3.1 --- a/src/pvr2/glutil.c Sun Oct 24 15:22:59 2010 +10003.2 +++ b/src/pvr2/glutil.c Tue Oct 26 08:39:02 2010 +10003.3 @@ -41,6 +41,18 @@3.4 return isGLExtensionSupported("GL_ARB_texture_mirrored_repeat");3.5 }3.7 +/**3.8 + * Check if there's at least 2 texture units3.9 + */3.10 +gboolean isGLMultitextureSupported()3.11 +{3.12 + if( !isGLExtensionSupported("GL_ARB_multitexture") )3.13 + return FALSE;3.14 + int units = 0;3.15 + glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &units);3.16 + return units >= 2;3.17 +}3.18 +3.19 gboolean isGLVertexRangeSupported()3.20 {3.21 return isGLExtensionSupported("GL_APPLE_vertex_array_range") ||
4.1 --- a/src/pvr2/glutil.h Sun Oct 24 15:22:59 2010 +10004.2 +++ b/src/pvr2/glutil.h Tue Oct 26 08:39:02 2010 +10004.3 @@ -47,6 +47,7 @@4.4 gboolean isGLVertexBufferSupported();4.5 gboolean isGLVertexRangeSupported();4.6 gboolean isGLPixelBufferSupported();4.7 +gboolean isGLMultitextureSupported();4.8 gboolean isGLMirroredTextureSupported();4.10 /****** Shader handling (gl_sl.c) *****/4.11 @@ -56,6 +57,8 @@4.12 void glsl_unload_shaders(void);4.13 gboolean glsl_set_shader( unsigned program_id );4.14 void glsl_clear_shader();4.15 +GLint glsl_get_uniform_location( unsigned program, const char *name );4.16 +void glsl_set_uniform_int( unsigned program, const char *name, GLint value );4.18 /* Convenience formatting function for driver use */4.19 void fprint_extensions( FILE *out, const char *extensions );
5.1 --- a/src/pvr2/scene.c Sun Oct 24 15:22:59 2010 +10005.2 +++ b/src/pvr2/scene.c Tue Oct 26 08:39:02 2010 +10005.3 @@ -226,6 +226,18 @@5.4 return poly;5.5 }5.7 +static float scene_get_palette_offset( uint32_t tex )5.8 +{5.9 + uint32_t fmt = (tex & PVR2_TEX_FORMAT_MASK);5.10 + if( fmt == PVR2_TEX_FORMAT_IDX4 ) {5.11 + return ((float)((tex & 0x07E00000) >> 17))/1024.0 + 0.0002;5.12 + } else if( fmt == PVR2_TEX_FORMAT_IDX8 ) {5.13 + return ((float)((tex & 0x06000000) >> 17))/1024.0 + 0.0002;5.14 + } else {5.15 + return -1.0;5.16 + }5.17 +}5.18 +5.19 /**5.20 * Decode a single PVR2 renderable vertex (opaque/trans/punch-out, but not shadow5.21 * volume)5.22 @@ -237,7 +249,7 @@5.23 * the normal vertex, half the vertex length for the modified vertex.5.24 */5.25 static void pvr2_decode_render_vertex( struct vertex_struct *vert, uint32_t poly1,5.26 - uint32_t poly2, uint32_t *pvr2_data,5.27 + uint32_t poly2, uint32_t tex, uint32_t *pvr2_data,5.28 int modify_offset )5.29 {5.30 gboolean force_alpha = !POLY2_ALPHA_ENABLE(poly2);5.31 @@ -279,16 +291,25 @@5.32 switch( POLY2_TEX_BLEND(poly2) ) {5.33 case 0:/* Convert replace => modulate by setting colour values to 1.0 */5.34 vert->rgba[0] = vert->rgba[1] = vert->rgba[2] = vert->rgba[3] = 1.0;5.35 + vert->tex_mode = 0.0;5.36 data.ival++; /* Skip the colour word */5.37 break;5.38 + case 2: /* Decal */5.39 + vert->tex_mode = 1.0;5.40 + unpack_bgra(*data.ival++, vert->rgba);5.41 + break;5.42 case 1:5.43 force_alpha = TRUE;5.44 /* fall-through */5.45 - default: /* Can't handle decal this way */5.46 + default:5.47 + vert->tex_mode = 0.0;5.48 unpack_bgra(*data.ival++, vert->rgba);5.49 break;5.50 }5.51 + vert->r = scene_get_palette_offset(tex);5.52 } else {5.53 + vert->tex_mode = 2.0;5.54 + vert->r = -1.0;5.55 unpack_bgra(*data.ival++, vert->rgba);5.56 }5.58 @@ -357,6 +378,8 @@5.59 result[i].z = rz;5.60 result[i].u = input[1].u + (t*tu) + (s*su);5.61 result[i].v = input[1].v + (t*tv) + (s*sv);5.62 + result[i].r = input[1].r; /* Last two components are flat */5.63 + result[i].tex_mode = input[1].tex_mode;5.65 if( is_solid_shaded ) {5.66 memcpy( result->rgba, input[2].rgba, sizeof(result->rgba) );5.67 @@ -503,6 +526,8 @@5.68 dest->z = src->z;5.69 dest->u = src->u;5.70 dest->v = src->v;5.71 + dest->r = src->r;5.72 + dest->tex_mode = src->tex_mode;5.73 dest->rgba[0] = src->rgba[0] * scene_shadow_intensity;5.74 dest->rgba[1] = src->rgba[1] * scene_shadow_intensity;5.75 dest->rgba[2] = src->rgba[2] * scene_shadow_intensity;5.76 @@ -531,7 +556,7 @@5.77 assert( poly != NULL );5.78 assert( pvr2_scene.vertex_index + poly->vertex_count <= pvr2_scene.vertex_count );5.79 for( i=0; i<poly->vertex_count; i++ ) {5.80 - pvr2_decode_render_vertex( &pvr2_scene.vertex_array[pvr2_scene.vertex_index++], context[0], context[1], ptr, 0 );5.81 + pvr2_decode_render_vertex( &pvr2_scene.vertex_array[pvr2_scene.vertex_index++], context[0], context[1], context[2], ptr, 0 );5.82 ptr += vertex_length;5.83 }5.84 if( is_modified ) {5.85 @@ -541,7 +566,7 @@5.86 int mod_offset = (vertex_length - 3)>>1;5.87 ptr = &pvr2_scene.pvr2_pbuf[poly_idx] + 5;5.88 for( i=0; i<poly->vertex_count; i++ ) {5.89 - pvr2_decode_render_vertex( &pvr2_scene.vertex_array[pvr2_scene.vertex_index++], context[0], context[3], ptr, mod_offset );5.90 + pvr2_decode_render_vertex( &pvr2_scene.vertex_array[pvr2_scene.vertex_index++], context[0], context[3], context[4], ptr, mod_offset );5.91 ptr += vertex_length;5.92 }5.93 } else {5.94 @@ -572,7 +597,7 @@5.95 ptr += (is_modified == SHADOW_FULL ? 5 : 3 );5.96 poly->vertex_index = pvr2_scene.vertex_index;5.97 for( i=0; i<4; i++ ) {5.98 - pvr2_decode_render_vertex( &quad[i], context[0], context[1], ptr, 0 );5.99 + pvr2_decode_render_vertex( &quad[i], context[0], context[1], context[2], ptr, 0 );5.100 ptr += vertex_length;5.101 }5.102 scene_compute_vertexes( &quad[3], 1, &quad[0], !POLY1_GOURAUD_SHADED(context[0]) );5.103 @@ -589,7 +614,7 @@5.104 int mod_offset = (vertex_length - 3)>>1;5.105 ptr = &pvr2_scene.pvr2_pbuf[poly_idx] + 5;5.106 for( i=0; i<4; i++ ) {5.107 - pvr2_decode_render_vertex( &quad[4], context[0], context[3], ptr, mod_offset );5.108 + pvr2_decode_render_vertex( &quad[4], context[0], context[3], context[4], ptr, mod_offset );5.109 ptr += vertex_length;5.110 }5.111 scene_compute_vertexes( &quad[3], 1, &quad[0], !POLY1_GOURAUD_SHADED(context[0]) );5.112 @@ -759,7 +784,7 @@5.113 struct vertex_struct base_vertexes[3];5.114 uint32_t *ptr = context + context_length;5.115 for( i=0; i<3; i++ ) {5.116 - pvr2_decode_render_vertex( &base_vertexes[i], context[0], context[1],5.117 + pvr2_decode_render_vertex( &base_vertexes[i], context[0], context[1], context[2],5.118 ptr, 0 );5.119 ptr += vertex_length;5.120 }5.121 @@ -774,7 +799,7 @@5.122 int mod_offset = (vertex_length - 3)>>1;5.123 ptr = context + context_length;5.124 for( i=0; i<3; i++ ) {5.125 - pvr2_decode_render_vertex( &base_vertexes[i], context[0], context[3],5.126 + pvr2_decode_render_vertex( &base_vertexes[i], context[0], context[3], context[4],5.127 ptr, mod_offset );5.128 ptr += vertex_length;5.129 }
6.1 --- a/src/pvr2/scene.h Sun Oct 24 15:22:59 2010 +10006.2 +++ b/src/pvr2/scene.h Tue Oct 26 08:39:02 2010 +10006.3 @@ -35,7 +35,7 @@6.6 struct vertex_struct {6.7 - float u,v;6.8 + float u,v,r,tex_mode; /* tex-coord quad */6.9 float x,y,z;6.10 float rgba[4];6.11 float offset_rgba[4];
7.1 --- a/src/pvr2/shaders.glsl Sun Oct 24 15:22:59 2010 +10007.2 +++ b/src/pvr2/shaders.glsl Tue Oct 26 08:39:02 2010 +10007.3 @@ -19,6 +19,52 @@7.4 * GNU General Public License for more details.7.5 */7.7 +/**7.8 + * Quick reference for predefined variables7.9 +7.10 + * Vertex shader input variables:7.11 + * vec4 gl_Color;7.12 + * vec4 gl_SecondaryColor;7.13 + * vec3 gl_Normal;7.14 + * vec4 gl_Vertex;7.15 + * vec4 gl_MultiTexCoord0;7.16 + * vec4 gl_MultiTexCoord1;7.17 + * vec4 gl_MultiTexCoord2;7.18 + * vec4 gl_MultiTexCoord3;7.19 + * vec4 gl_MultiTexCoord4;7.20 + * vec4 gl_MultiTexCoord5;7.21 + * vec4 gl_MultiTexCoord6;7.22 + * vec4 gl_MultiTexCoord7;7.23 + * float gl_FogCoord;7.24 + *7.25 + * Vertex shader output variables:7.26 + * vec4 gl_Position; // must be written to7.27 + * float gl_PointSize; // may be written to7.28 + * vec4 gl_ClipVertex; // may be written to7.29 + * varying vec4 gl_FrontColor;7.30 + * varying vec4 gl_BackColor;7.31 + * varying vec4 gl_FrontSecondaryColor;7.32 + * varying vec4 gl_BackSecondaryColor;7.33 + * varying vec4 gl_TexCoord[]; // at most will be gl_MaxTextureCoords7.34 + * varying float gl_FogFragCoord;7.35 + *7.36 + * Fragment shader input variables:7.37 + * varying vec4 gl_Color;7.38 + * varying vec4 gl_SecondaryColor;7.39 + * varying vec4 gl_TexCoord[]; // at most will be gl_MaxTextureCoords7.40 + * varying float gl_FogFragCoord;7.41 + * varying vec2 gl_PointCoord;7.42 + *7.43 + * Fragme shader output variables:7.44 + * vec4 gl_FragCoord;7.45 + * bool gl_FrontFacing;7.46 + * vec4 gl_FragColor;7.47 + * vec4 gl_FragData[gl_MaxDrawBuffers];7.48 + * float gl_FragDepth;7.49 +7.50 + */7.51 +7.52 +7.53 #vertex DEFAULT_VERTEX_SHADER7.54 void main()7.55 {7.56 @@ -32,11 +78,32 @@7.57 }7.59 #fragment DEFAULT_FRAGMENT_SHADER7.60 +7.61 +uniform sampler2D primary_texture;7.62 +uniform sampler1D palette_texture;7.63 +7.64 void main()7.65 {7.66 - gl_FragColor = gl_Color;7.67 + vec4 tex = texture2D( primary_texture, gl_TexCoord[0].xy );7.68 + if( gl_TexCoord[0].z >= 0.0 ) {7.69 + tex = texture1D( palette_texture, gl_TexCoord[0].z + (tex.a*0.249023) );7.70 + }7.71 + /* HACK: unfortunately we have to maintain compatibility with GLSL 1.20,7.72 + * which only supports varying float. So since we're propagating texcoord7.73 + * anyway, overload the last component to indicate texture mode.7.74 + */7.75 + if( gl_TexCoord[0].w == 0.0 ) {7.76 + gl_FragColor.rgb = mix( gl_Color.rgb * tex.rgb + gl_SecondaryColor.rgb, gl_Fog.color.rgb, gl_FogFragCoord );7.77 + gl_FragColor.a = gl_Color.a * tex.a;7.78 + } else if( gl_TexCoord[0].w >= 1.5 ) {7.79 + gl_FragColor.rgb = mix( gl_Color.rgb, gl_Fog.color.rgb, gl_FogFragCoord );7.80 + gl_FragColor.a = gl_Color.a;7.81 + } else {7.82 + gl_FragColor.rgb = mix( mix(gl_Color.rgb,tex.rgb,tex.a) + gl_SecondaryColor.rgb, gl_Fog.color.rgb, gl_FogFragCoord);7.83 + gl_FragColor.a = gl_Color.a;7.84 + }7.85 gl_FragDepth = gl_FragCoord.z;7.86 }7.88 -#program DEFAULT_PROGRAM = DEFAULT_VERTEX_SHADER7.89 +#program DEFAULT_PROGRAM = DEFAULT_VERTEX_SHADER DEFAULT_FRAGMENT_SHADER
8.1 --- a/src/pvr2/texcache.c Sun Oct 24 15:22:59 2010 +10008.2 +++ b/src/pvr2/texcache.c Tue Oct 26 08:39:02 2010 +10008.3 @@ -22,6 +22,7 @@8.4 #include <string.h>8.5 #include "pvr2/pvr2.h"8.6 #include "pvr2/pvr2mmio.h"8.7 +#include "pvr2/glutil.h"8.9 /** Specifies the maximum number of OpenGL8.10 * textures we're willing to have open at a time. If more are8.11 @@ -59,6 +60,9 @@8.12 static struct texcache_entry texcache_active_list[MAX_TEXTURES];8.13 static uint32_t texcache_palette_mode;8.14 static uint32_t texcache_stride_width;8.15 +static gboolean texcache_have_palette_shader;8.16 +static gboolean texcache_palette_valid;8.17 +static GLuint texcache_palette_texid;8.19 /**8.20 * Initialize the texture cache.8.21 @@ -77,7 +81,7 @@8.22 }8.23 texcache_free_ptr = 0;8.24 texcache_ref_counter = 0;8.25 - texcache_palette_mode = 0;8.26 + texcache_palette_mode = -1;8.27 texcache_stride_width = 0;8.28 }8.30 @@ -90,6 +94,23 @@8.31 int i;8.32 GLuint texids[MAX_TEXTURES];8.34 + if( glsl_is_supported() && isGLMultitextureSupported ) {8.35 + texcache_have_palette_shader = TRUE;8.36 + texcache_palette_valid = FALSE;8.37 + glGenTextures(1, &texcache_palette_texid );8.38 +8.39 + /* Bind the texture and set the params */8.40 + glActiveTexture(GL_TEXTURE1);8.41 + glBindTexture(GL_TEXTURE_1D, texcache_palette_texid);8.42 + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);8.43 + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);8.44 + glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP );8.45 + glActiveTexture(GL_TEXTURE0);8.46 +8.47 + } else {8.48 + texcache_have_palette_shader = FALSE;8.49 + }8.50 +8.51 glGenTextures( MAX_TEXTURES, texids );8.52 for( i=0; i<MAX_TEXTURES; i++ ) {8.53 texcache_active_list[i].texture_id = texids[i];8.54 @@ -137,6 +158,9 @@8.55 int i;8.56 texcache_flush();8.58 + if( texcache_have_palette_shader )8.59 + glDeleteTextures( 1, &texcache_palette_texid );8.60 +8.61 for( i=0; i<MAX_TEXTURES; i++ ) {8.62 texids[i] = texcache_active_list[i].texture_id;8.63 }8.64 @@ -220,20 +244,83 @@8.65 }8.67 /**8.68 - * Mark all textures that use the palette table as needing a re-read (ie8.69 - * for when the palette is changed. We could track exactly which ones are8.70 - * affected, but it's not clear that the extra maintanence overhead is8.71 - * worthwhile.8.72 + * Load the palette into 4 textures of 256 entries each. This mirrors the8.73 + * banking done by the PVR2 for 8-bit textures, and also ensures that we8.74 + * can use 8-bit paletted textures ourselves.8.75 + */8.76 +static void texcache_load_palette_texture( gboolean format_changed )8.77 +{8.78 + GLint format, type, intFormat = GL_RGBA;8.79 + unsigned i;8.80 + int bpp = 2;8.81 + uint32_t *palette = (uint32_t *)mmio_region_PVR2PAL.mem;8.82 + uint16_t packed_palette[1024];8.83 + char *data = (char *)palette;8.84 +8.85 + switch( texcache_palette_mode ) {8.86 + case 0: /* ARGB1555 */8.87 + format = GL_BGRA;8.88 + type = GL_UNSIGNED_SHORT_1_5_5_5_REV;8.89 + break;8.90 + case 1: /* RGB565 */8.91 + intFormat = GL_RGB;8.92 + format = GL_RGB;8.93 + type = GL_UNSIGNED_SHORT_5_6_5;8.94 + break;8.95 + case 2: /* ARGB4444 */8.96 + format = GL_BGRA;8.97 + type = GL_UNSIGNED_SHORT_4_4_4_4_REV;8.98 + break;8.99 + case 3: /* ARGB8888 */8.100 + format = GL_BGRA;8.101 + type = GL_UNSIGNED_BYTE;8.102 + bpp = 4;8.103 + break;8.104 + default:8.105 + break; /* Can't happen */8.106 + }8.107 +8.108 +8.109 + if( bpp == 2 ) {8.110 + for( i=0; i<1024; i++ ) {8.111 + packed_palette[i] = (uint16_t)palette[i];8.112 + }8.113 + data = (char *)packed_palette;8.114 +8.115 + }8.116 +8.117 + glActiveTexture(GL_TEXTURE1);8.118 +// glBindTexture(GL_TEXTURE_1D, texcache_palette_texid);8.119 + if( format_changed )8.120 + glTexImage1D(GL_TEXTURE_1D, 0, intFormat, 1024, 0, format, type, data );8.121 + else8.122 + glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 1024, format, type, data);8.123 +// glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);8.124 +// glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);8.125 +// glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP );8.126 + glActiveTexture(GL_TEXTURE0);8.127 + texcache_palette_valid = TRUE;8.128 +}8.129 +8.130 +8.131 +/**8.132 + * Mark the palette as having changed. If we have palette support (via shaders)8.133 + * we just flag the palette, otherwise we have to invalidate all palette8.134 + * textures.8.135 */8.136 void texcache_invalidate_palette( )8.137 {8.138 - int i;8.139 - for( i=0; i<MAX_TEXTURES; i++ ) {8.140 - if( texcache_active_list[i].texture_addr != -1 &&8.141 - PVR2_TEX_IS_PALETTE(texcache_active_list[i].tex_mode) ) {8.142 - texcache_evict( i );8.143 - texcache_free_ptr--;8.144 - texcache_free_list[texcache_free_ptr] = i;8.145 + if( texcache_have_palette_shader ) {8.146 + texcache_palette_valid = FALSE;8.147 + } else {8.148 + int i;8.149 + for( i=0; i<MAX_TEXTURES; i++ ) {8.150 + if( texcache_active_list[i].texture_addr != -1 &&8.151 + PVR2_TEX_IS_PALETTE(texcache_active_list[i].tex_mode) ) {8.152 + texcache_evict( i );8.153 + texcache_free_ptr--;8.154 + texcache_free_list[texcache_free_ptr] = i;8.155 + }8.156 }8.157 }8.158 }8.159 @@ -256,13 +343,19 @@8.161 void texcache_begin_scene( uint32_t palette_mode, uint32_t stride )8.162 {8.163 - if( palette_mode != texcache_palette_mode )8.164 + gboolean format_changed = FALSE;8.165 + if( palette_mode != texcache_palette_mode ) {8.166 texcache_invalidate_palette();8.167 + format_changed = TRUE;8.168 + }8.169 if( stride != texcache_stride_width )8.170 texcache_invalidate_stride();8.172 texcache_palette_mode = palette_mode;8.173 texcache_stride_width = stride;8.174 +8.175 + if( !texcache_palette_valid && texcache_have_palette_shader )8.176 + texcache_load_palette_texture(format_changed);8.177 }8.179 static void decode_pal8_to_32( uint32_t *out, uint8_t *in, int inbytes, uint32_t *pal )8.180 @@ -291,6 +384,17 @@8.181 }8.182 }8.184 +static void decode_pal4_to_pal8( uint8_t *out, uint8_t *in, int inbytes )8.185 +{8.186 + int i;8.187 + for( i=0; i<inbytes; i++ ) {8.188 + *out++ = (uint8_t)(*in & 0x0F);8.189 + *out++ = (uint8_t)(*in >> 4);8.190 + in++;8.191 + }8.192 +}8.193 +8.194 +8.196 static void decode_pal4_to_16( uint16_t *out, uint8_t *in, int inbytes, uint32_t *pal )8.197 {8.198 @@ -395,7 +499,9 @@8.199 GLint intFormat = GL_RGBA, format, type;8.200 int tex_format = mode & PVR2_TEX_FORMAT_MASK;8.201 struct vq_codebook codebook;8.202 - GLint filter = GL_LINEAR;8.203 + GLint min_filter = GL_LINEAR;8.204 + GLint max_filter = GL_LINEAR;8.205 + GLint mipmapfilter = GL_LINEAR_MIPMAP_LINEAR;8.207 glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );8.209 @@ -403,30 +509,39 @@8.210 switch( tex_format ) {8.211 case PVR2_TEX_FORMAT_IDX4:8.212 case PVR2_TEX_FORMAT_IDX8:8.213 - /* For indexed-colour modes, we need to lookup the palette control8.214 - * word to determine the de-indexed texture format.8.215 - */8.216 - switch( texcache_palette_mode ) {8.217 - case 0: /* ARGB1555 */8.218 - format = GL_BGRA;8.219 - type = GL_UNSIGNED_SHORT_1_5_5_5_REV;8.220 - break;8.221 - case 1: /* RGB565 */8.222 - intFormat = GL_RGB;8.223 - format = GL_RGB;8.224 - type = GL_UNSIGNED_SHORT_5_6_5;8.225 - break;8.226 - case 2: /* ARGB4444 */8.227 - format = GL_BGRA;8.228 - type = GL_UNSIGNED_SHORT_4_4_4_4_REV;8.229 - break;8.230 - case 3: /* ARGB8888 */8.231 - format = GL_BGRA;8.232 + if( texcache_have_palette_shader ) {8.233 + intFormat = GL_ALPHA8;8.234 + format = GL_ALPHA;8.235 type = GL_UNSIGNED_BYTE;8.236 - bpp_shift = 2;8.237 - break;8.238 - default:8.239 - return; /* Can't happen, but it makes gcc stop complaining */8.240 + bpp_shift = 0;8.241 + min_filter = max_filter = GL_NEAREST;8.242 + mipmapfilter = GL_NEAREST_MIPMAP_NEAREST;8.243 + } else {8.244 + /* For indexed-colour modes, we need to lookup the palette control8.245 + * word to determine the de-indexed texture format.8.246 + */8.247 + switch( texcache_palette_mode ) {8.248 + case 0: /* ARGB1555 */8.249 + format = GL_BGRA;8.250 + type = GL_UNSIGNED_SHORT_1_5_5_5_REV;8.251 + break;8.252 + case 1: /* RGB565 */8.253 + intFormat = GL_RGB;8.254 + format = GL_RGB;8.255 + type = GL_UNSIGNED_SHORT_5_6_5;8.256 + break;8.257 + case 2: /* ARGB4444 */8.258 + format = GL_BGRA;8.259 + type = GL_UNSIGNED_SHORT_4_4_4_4_REV;8.260 + break;8.261 + case 3: /* ARGB8888 */8.262 + format = GL_BGRA;8.263 + type = GL_UNSIGNED_BYTE;8.264 + bpp_shift = 2;8.265 + break;8.266 + default:8.267 + return; /* Can't happen, but it makes gcc stop complaining */8.268 + }8.269 }8.270 break;8.272 @@ -469,8 +584,8 @@8.273 pvr2_vram64_read_stride( data, width<<bpp_shift, texture_addr, texcache_stride_width<<bpp_shift, height );8.274 }8.275 glTexImage2D( GL_TEXTURE_2D, 0, intFormat, width, height, 0, format, type, data );8.276 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);8.277 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);8.278 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter);8.279 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, max_filter);8.280 return;8.281 }8.283 @@ -484,7 +599,7 @@8.284 int level=0, last_level = 0, mip_width = width, mip_height = height, src_bytes, dest_bytes;8.285 if( PVR2_TEX_IS_MIPMAPPED(mode) ) {8.286 uint32_t src_offset = 0;8.287 - filter = GL_LINEAR_MIPMAP_LINEAR;8.288 + min_filter = mipmapfilter;8.289 mip_height = height = width;8.290 while( (1<<last_level) < width ) {8.291 last_level++;8.292 @@ -513,26 +628,35 @@8.293 unsigned char data[dest_bytes];8.294 /* load data from image, detwiddling/uncompressing as required */8.295 if( tex_format == PVR2_TEX_FORMAT_IDX8 ) {8.296 - src_bytes = (mip_width * mip_height);8.297 - int bank = (mode >> 25) &0x03;8.298 - uint32_t *palette = ((uint32_t *)mmio_region_PVR2PAL.mem) + (bank<<8);8.299 - unsigned char tmp[src_bytes];8.300 - pvr2_vram64_read_twiddled_8( tmp, texture_addr, mip_width, mip_height );8.301 - if( bpp_shift == 2 ) {8.302 - decode_pal8_to_32( (uint32_t *)data, tmp, src_bytes, palette );8.303 + if( texcache_have_palette_shader ) {8.304 + pvr2_vram64_read_twiddled_8( data, texture_addr, mip_width, mip_height );8.305 } else {8.306 - decode_pal8_to_16( (uint16_t *)data, tmp, src_bytes, palette );8.307 + src_bytes = (mip_width * mip_height);8.308 + int bank = (mode >> 25) &0x03;8.309 + uint32_t *palette = ((uint32_t *)mmio_region_PVR2PAL.mem) + (bank<<8);8.310 + unsigned char tmp[src_bytes];8.311 + pvr2_vram64_read_twiddled_8( tmp, texture_addr, mip_width, mip_height );8.312 + if( bpp_shift == 2 ) {8.313 + decode_pal8_to_32( (uint32_t *)data, tmp, src_bytes, palette );8.314 + } else {8.315 + decode_pal8_to_16( (uint16_t *)data, tmp, src_bytes, palette );8.316 + }8.317 }8.318 } else if( tex_format == PVR2_TEX_FORMAT_IDX4 ) {8.319 src_bytes = (mip_width * mip_height) >> 1;8.320 - int bank = (mode >>21 ) & 0x3F;8.321 - uint32_t *palette = ((uint32_t *)mmio_region_PVR2PAL.mem) + (bank<<4);8.322 unsigned char tmp[src_bytes];8.323 - pvr2_vram64_read_twiddled_4( tmp, texture_addr, mip_width, mip_height );8.324 - if( bpp_shift == 2 ) {8.325 - decode_pal4_to_32( (uint32_t *)data, tmp, src_bytes, palette );8.326 + if( texcache_have_palette_shader ) {8.327 + pvr2_vram64_read_twiddled_4( tmp, texture_addr, mip_width, mip_height );8.328 + decode_pal4_to_pal8( data, tmp, src_bytes );8.329 } else {8.330 - decode_pal4_to_16( (uint16_t *)data, tmp, src_bytes, palette );8.331 + int bank = (mode >>21 ) & 0x3F;8.332 + uint32_t *palette = ((uint32_t *)mmio_region_PVR2PAL.mem) + (bank<<4);8.333 + pvr2_vram64_read_twiddled_4( tmp, texture_addr, mip_width, mip_height );8.334 + if( bpp_shift == 2 ) {8.335 + decode_pal4_to_32( (uint32_t *)data, tmp, src_bytes, palette );8.336 + } else {8.337 + decode_pal4_to_16( (uint16_t *)data, tmp, src_bytes, palette );8.338 + }8.339 }8.340 } else if( tex_format == PVR2_TEX_FORMAT_YUV422 ) {8.341 src_bytes = ((mip_width*mip_height)<<1);8.342 @@ -575,8 +699,8 @@8.343 }8.344 }8.346 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);8.347 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);8.348 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter);8.349 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, max_filter);8.350 }8.352 static int texcache_find_texture_slot( uint32_t poly2_masked_word, uint32_t texture_word )8.353 @@ -646,11 +770,15 @@8.354 GLuint texcache_get_texture( uint32_t poly2_word, uint32_t texture_word )8.355 {8.356 poly2_word &= 0x000F803F; /* Get just the texture-relevant bits */8.357 - int slot = texcache_find_texture_slot( poly2_word, texture_word );8.358 + uint32_t texture_lookup = texture_word;8.359 + if( PVR2_TEX_IS_PALETTE(texture_lookup) ) {8.360 + texture_lookup &= 0xF81FFFFF; /* Mask out the bank bits */8.361 + }8.362 + int slot = texcache_find_texture_slot( poly2_word, texture_lookup );8.364 if( slot == -1 ) {8.365 /* Not found - check the free list */8.366 - slot = texcache_alloc_texture_slot( poly2_word, texture_word );8.367 + slot = texcache_alloc_texture_slot( poly2_word, texture_lookup );8.369 /* Construct the GL texture */8.370 uint32_t texture_addr = (texture_word & 0x000FFFFF)<<3;8.371 @@ -750,3 +878,23 @@8.372 assert( slot_found[i] != 0 );8.373 }8.374 }8.375 +8.376 +/**8.377 + * Dump the contents of the texture cache8.378 + */8.379 +void texcache_dump()8.380 +{8.381 + unsigned i;8.382 + for( i=0; i< PVR2_RAM_PAGES; i++ ) {8.383 + int slot = texcache_page_lookup[i];8.384 + while( slot != EMPTY_ENTRY ) {8.385 + fprintf( stderr, "%-3d: %08X %dx%d (%08X %08X)\n", slot,8.386 + texcache_active_list[slot].texture_addr,8.387 + POLY2_TEX_WIDTH(texcache_active_list[slot].poly2_mode),8.388 + POLY2_TEX_HEIGHT(texcache_active_list[slot].poly2_mode),8.389 + texcache_active_list[slot].poly2_mode,8.390 + texcache_active_list[slot].tex_mode );8.391 + slot = texcache_active_list[slot].next;8.392 + }8.393 + }8.394 +}
.