Search
lxdream.org :: lxdream/src/pvr2/texcache.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/texcache.c
changeset 856:02ac5f37bfc9
prev736:a02d1475ccfd
next860:b429964761c8
author nkeynes
date Thu Sep 11 22:51:24 2008 +0000 (13 years ago)
permissions -rw-r--r--
last change Completely untested render-to-texture work in progress
file annotate diff log raw
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.3 @@ -49,6 +49,7 @@
1.4 uint32_t texture_addr;
1.5 int width, height, mode;
1.6 GLuint texture_id;
1.7 + render_buffer_t buffer;
1.8 texcache_entry_index next;
1.9 uint32_t lru_count;
1.10 } *texcache_entry_t;
1.11 @@ -69,6 +70,7 @@
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.17 }
1.18 texcache_free_ptr = 0;
1.19 @@ -90,6 +92,13 @@
1.20 }
1.21 }
1.22
1.23 +void texcache_release_render_buffer( render_buffer_t buffer )
1.24 +{
1.25 + if( !buffer->flushed )
1.26 + pvr2_render_buffer_copy_to_sh4(buffer);
1.27 + pvr2_destroy_render_buffer(buffer);
1.28 +}
1.29 +
1.30 /**
1.31 * Flush all textures from the cache, returning them to the free list.
1.32 */
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.40 + }
1.41 }
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.51 + }
1.52 if( texcache_page_lookup[evict_page] == slot ) {
1.53 texcache_page_lookup[evict_page] = replace_next;
1.54 } else {
1.55 @@ -184,6 +201,10 @@
1.56 do {
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.62 + }
1.63 /* release entry */
1.64 texcache_free_ptr--;
1.65 texcache_free_list[texcache_free_ptr] = idx;
1.66 @@ -322,6 +343,16 @@
1.67 }
1.68 }
1.69
1.70 +static gboolean is_npot_texture( int width )
1.71 +{
1.72 + while( width != 0 ) {
1.73 + if( width & 1 )
1.74 + return width != 1;
1.75 + width >>= 1;
1.76 + }
1.77 + return TRUE;
1.78 +}
1.79 +
1.80 /**
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.85 }
1.86
1.87 -/**
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.93 - *
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.96 - */
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.99 {
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.107 + return idx;
1.108 }
1.109 idx = entry->next;
1.110 }
1.111 + return -1;
1.112 +}
1.113
1.114 -
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.117 +{
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.121
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.125
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.130 int i;
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.136 + return slot;
1.137 +}
1.138
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.142 +/**
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.148 + *
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.151 + */
1.152 +GLuint texcache_get_texture( uint32_t texture_word, int width, int height )
1.153 +{
1.154 + int slot = texcache_find_texture_slot( texture_word, width, height );
1.155 +
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.159 +
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.164 + }
1.165
1.166 return texcache_active_list[slot].texture_id;
1.167 }
1.168
1.169 +render_buffer_t texcache_get_render_buffer( uint32_t texture_addr, int mode, int width, int height )
1.170 +{
1.171 + INFO( "Rendering to texture!" );
1.172 + uint32_t texture_word = ((texture_addr >> 3) & 0x000FFFFF) | PVR2_TEX_UNTWIDDLED;
1.173 + switch( mode ) {
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.177 + default:
1.178 + WARN( "Rendering to non-texture colour format" );
1.179 + }
1.180 + if( is_npot_texture(width) )
1.181 + texture_word |= PVR2_TEX_STRIDE;
1.182 +
1.183 +
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.187 + }
1.188 +
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.195 + }
1.196 + entry->buffer = pvr2_create_render_buffer( texture_addr, width, height, entry->texture_id );
1.197 + } else {
1.198 + if( entry->buffer == NULL )
1.199 + entry->buffer = pvr2_create_render_buffer( texture_addr, width, height, entry->texture_id );
1.200 + }
1.201 +
1.202 + return entry->buffer;
1.203 +}
1.204 +
1.205 /**
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
.