+static void _sw_cache_push( struct cached_player *player )
+{
+ player->l = NULL;
+ player->r = steam_api_classes.cache_head;
+ if( steam_api_classes.cache_head ) steam_api_classes.cache_head->l = player;
+ if( !steam_api_classes.cache_tail ) steam_api_classes.cache_tail = player;
+ steam_api_classes.cache_head = player;
+ steam_api_classes.cache_count ++;
+}
+
+static void _sw_cache_evict( struct cached_player *player )
+{
+ if( player == steam_api_classes.cache_tail ) steam_api_classes.cache_tail = player->l;
+ if( player == steam_api_classes.cache_head ) steam_api_classes.cache_head = player->r;
+ if( player->l ) player->l->r = player->r;
+ if( player->r ) player->r->l = player->l;
+ steam_api_classes.cache_count --;
+}
+
+static void _sw_access_cache( struct cached_player *player )
+{
+ _sw_cache_evict( player );
+ _sw_cache_push( player );
+}
+
+static GLuint sw_get_player_image( u64_steamid usr )
+{
+ // Look for player in cache
+ for( int i = 0; i < steam_api_classes.cache_count; i ++ )
+ {
+ struct cached_player *player = &steam_api_classes.cached_players[i];
+
+ if( player->id == usr )
+ {
+ _sw_access_cache( player );
+ return player->avatar_texture;
+ }
+ }
+
+ struct cached_player *dest;
+
+ if( steam_api_classes.cache_count == vg_list_size( steam_api_classes.cached_players ) )
+ {
+ dest = steam_api_classes.cache_tail;
+ _sw_access_cache( dest );
+
+ // Delete previous before creating a new one
+ glDeleteTextures( 1, &dest->avatar_texture );
+ }
+ else
+ {
+ dest = &steam_api_classes.cached_players[ steam_api_classes.cache_count ];
+ _sw_cache_push( dest );
+ }
+
+ dest->id = usr;
+ dest->avatar_texture = 0;
+
+ // Upload new image
+ u32 x = 32, y = 32;
+ int steam_image;
+
+ steam_image = sw_get_small_friend_avatar( usr );
+ if( !steam_image )
+ return 0;
+
+ if( !sw_get_image_size( steam_image, &x, &y ) )
+ return 0;
+
+ u8 * img_buf = (u8 *)malloc( x * y * 4 );
+
+ if( !sw_get_image_rgba(steam_image, img_buf, x * y * 4) )
+ {
+ free( img_buf );
+ return 0;
+ }
+
+ glGenTextures( 1, &dest->avatar_texture );
+ glBindTexture( GL_TEXTURE_2D, dest->avatar_texture );
+
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, img_buf );
+ glGenerateMipmap( GL_TEXTURE_2D );
+
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+
+ free( img_buf );
+
+ return dest->avatar_texture;
+}
+