1.1 --- a/src/pvr2/texcache.c Mon Jul 14 07:44:42 2008 +0000
1.2 +++ b/src/pvr2/texcache.c Thu Sep 11 22:51:24 2008 +0000
1.4 uint32_t texture_addr;
1.5 int width, height, mode;
1.7 + render_buffer_t buffer;
1.8 texcache_entry_index next;
1.10 } *texcache_entry_t;
1.12 for( i=0; i<MAX_TEXTURES; i++ ) {
1.13 texcache_free_list[i] = i;
1.14 texcache_active_list[i].texture_addr = -1;
1.15 + texcache_active_list[i].buffer = NULL;
1.16 texcache_active_list[i].next = EMPTY_ENTRY;
1.18 texcache_free_ptr = 0;
1.23 +void texcache_release_render_buffer( render_buffer_t buffer )
1.25 + if( !buffer->flushed )
1.26 + pvr2_render_buffer_copy_to_sh4(buffer);
1.27 + pvr2_destroy_render_buffer(buffer);
1.31 * Flush all textures from the cache, returning them to the free list.
1.33 @@ -103,6 +112,10 @@
1.34 for( i=0; i<MAX_TEXTURES; i++ ) {
1.35 texcache_free_list[i] = i;
1.36 texcache_active_list[i].next = EMPTY_ENTRY;
1.37 + if( texcache_active_list[i].buffer != NULL ) {
1.38 + texcache_release_render_buffer(texcache_active_list[i].buffer);
1.39 + texcache_active_list[i].buffer = NULL;
1.42 texcache_free_ptr = 0;
1.43 texcache_ref_counter = 0;
1.44 @@ -133,6 +146,10 @@
1.45 texcache_entry_index replace_next = texcache_active_list[slot].next;
1.46 texcache_active_list[slot].texture_addr = -1;
1.47 texcache_active_list[slot].next = EMPTY_ENTRY; /* Just for safety */
1.48 + if( texcache_active_list[slot].buffer != NULL ) {
1.49 + texcache_release_render_buffer(texcache_active_list[slot].buffer);
1.50 + texcache_active_list[slot].buffer = NULL;
1.52 if( texcache_page_lookup[evict_page] == slot ) {
1.53 texcache_page_lookup[evict_page] = replace_next;
1.55 @@ -184,6 +201,10 @@
1.57 texcache_entry_t entry = &texcache_active_list[idx];
1.58 entry->texture_addr = -1;
1.59 + if( entry->buffer != NULL ) {
1.60 + texcache_release_render_buffer(entry->buffer);
1.61 + entry->buffer = NULL;
1.64 texcache_free_ptr--;
1.65 texcache_free_list[texcache_free_ptr] = idx;
1.66 @@ -322,6 +343,16 @@
1.70 +static gboolean is_npot_texture( int width )
1.72 + while( width != 0 ) {
1.74 + return width != 1;
1.81 * Load texture data from the given address and parameters into the currently
1.82 * bound OpenGL texture.
1.83 @@ -519,17 +550,7 @@
1.84 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1.88 - * Return a texture ID for the texture specified at the supplied address
1.89 - * and given parameters (the same sequence of bytes could in theory have
1.90 - * multiple interpretations). We use the texture address as the primary
1.91 - * index, but allow for multiple instances at each address. The texture
1.92 - * will be bound to the GL_TEXTURE_2D target before being returned.
1.94 - * If the texture has already been bound, return the ID to which it was
1.95 - * bound. Otherwise obtain an unused texture ID and set it up appropriately.
1.97 -GLuint texcache_get_texture( uint32_t texture_word, int width, int height )
1.98 +static int texcache_find_texture_slot( uint32_t texture_word, int width, int height )
1.100 uint32_t texture_addr = (texture_word & 0x000FFFFF)<<3;
1.101 uint32_t texture_page = texture_addr >> 12;
1.102 @@ -542,13 +563,17 @@
1.103 entry->width == width &&
1.104 entry->height == height ) {
1.105 entry->lru_count = texcache_ref_counter++;
1.106 - return entry->texture_id;
1.115 - /* Not found - check the free list */
1.116 +static int texcache_alloc_texture_slot( uint32_t texture_word, int width, int height )
1.118 + uint32_t texture_addr = (texture_word & 0x000FFFFF)<<3;
1.119 + uint32_t texture_page = texture_addr >> 12;
1.120 texcache_entry_index slot = 0;
1.122 if( texcache_free_ptr < MAX_TEXTURES ) {
1.123 @@ -565,7 +590,7 @@
1.124 texcache_active_list[slot].lru_count = texcache_ref_counter++;
1.126 /* Add entry to the lookup table */
1.127 - next = texcache_page_lookup[texture_page];
1.128 + int next = texcache_page_lookup[texture_page];
1.129 if( next == slot ) {
1.131 fprintf( stderr, "Active list: " );
1.132 @@ -579,14 +604,72 @@
1.133 assert( next != slot );
1.134 texcache_active_list[slot].next = next;
1.135 texcache_page_lookup[texture_page] = slot;
1.139 - /* Construct the GL texture */
1.140 - glBindTexture( GL_TEXTURE_2D, texcache_active_list[slot].texture_id );
1.141 - texcache_load_texture( texture_addr, width, height, texture_word );
1.143 + * Return a texture ID for the texture specified at the supplied address
1.144 + * and given parameters (the same sequence of bytes could in theory have
1.145 + * multiple interpretations). We use the texture address as the primary
1.146 + * index, but allow for multiple instances at each address. The texture
1.147 + * will be bound to the GL_TEXTURE_2D target before being returned.
1.149 + * If the texture has already been bound, return the ID to which it was
1.150 + * bound. Otherwise obtain an unused texture ID and set it up appropriately.
1.152 +GLuint texcache_get_texture( uint32_t texture_word, int width, int height )
1.154 + int slot = texcache_find_texture_slot( texture_word, width, height );
1.156 + if( slot == -1 ) {
1.157 + /* Not found - check the free list */
1.158 + slot = texcache_alloc_texture_slot( texture_word, width, height );
1.160 + /* Construct the GL texture */
1.161 + uint32_t texture_addr = (texture_word & 0x000FFFFF)<<3;
1.162 + glBindTexture( GL_TEXTURE_2D, texcache_active_list[slot].texture_id );
1.163 + texcache_load_texture( texture_addr, width, height, texture_word );
1.166 return texcache_active_list[slot].texture_id;
1.169 +render_buffer_t texcache_get_render_buffer( uint32_t texture_addr, int mode, int width, int height )
1.171 + INFO( "Rendering to texture!" );
1.172 + uint32_t texture_word = ((texture_addr >> 3) & 0x000FFFFF) | PVR2_TEX_UNTWIDDLED;
1.174 + case COLFMT_BGRA1555: texture_word |= PVR2_TEX_FORMAT_ARGB1555; break;
1.175 + case COLFMT_RGB565: texture_word |= PVR2_TEX_FORMAT_RGB565; break;
1.176 + case COLFMT_BGRA4444: texture_word |= PVR2_TEX_FORMAT_ARGB4444; break;
1.178 + WARN( "Rendering to non-texture colour format" );
1.180 + if( is_npot_texture(width) )
1.181 + texture_word |= PVR2_TEX_STRIDE;
1.184 + int slot = texcache_find_texture_slot( texture_word, width, height );
1.185 + if( slot == -1 ) {
1.186 + slot = texcache_alloc_texture_slot( texture_word, width, height );
1.189 + texcache_entry_t entry = &texcache_active_list[slot];
1.190 + if( entry->width != width || entry->height != height ) {
1.191 + glBindTexture(GL_TEXTURE_2D, entry->texture_id );
1.192 + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1.193 + if( entry->buffer != NULL ) {
1.194 + texcache_release_render_buffer(entry->buffer);
1.196 + entry->buffer = pvr2_create_render_buffer( texture_addr, width, height, entry->texture_id );
1.198 + if( entry->buffer == NULL )
1.199 + entry->buffer = pvr2_create_render_buffer( texture_addr, width, height, entry->texture_id );
1.202 + return entry->buffer;
1.206 * Check the integrity of the texcache. Verifies that every cache slot
1.207 * appears exactly once on either the free list or one page list. For