Merge pull request #1784 from heuripedes/master

Fix XMB performance regression
This commit is contained in:
Twinaphex 2015-06-13 05:17:16 +02:00
commit ca7982e739
3 changed files with 97 additions and 50 deletions

View File

@ -995,12 +995,16 @@ static void xmb_draw_items(xmb_handle_t *xmb, gl_t *gl,
unsigned i; unsigned i;
unsigned width, height; unsigned width, height;
math_matrix_4x4 mymat, mrot, mscal; math_matrix_4x4 mymat, mrot, mscal;
const char *label = NULL; const char *label = NULL;
xmb_node_t *core_node = NULL; xmb_node_t *core_node = NULL;
size_t end = 0; size_t end = 0;
uint64_t frame_count = video_driver_get_frame_count(); uint64_t frame_count = video_driver_get_frame_count();
char name[PATH_MAX_LENGTH] = {0};
char value[PATH_MAX_LENGTH] = {0};
menu_entry_t entry = {{0}};
menu_handle_t *menu = menu_driver_get_ptr();
if (!list || !list->size) if (!list || !list->size || !menu)
return; return;
video_driver_get_size(&width, &height); video_driver_get_size(&width, &height);
@ -1021,17 +1025,18 @@ static void xmb_draw_items(xmb_handle_t *xmb, gl_t *gl,
for (i = 0; i < end; i++) for (i = 0; i < end; i++)
{ {
float icon_x, icon_y; float icon_x, icon_y;
char name[PATH_MAX_LENGTH] = {0};
char value[PATH_MAX_LENGTH] = {0};
menu_entry_t entry = {{0}};
GLuint texture_switch = 0; GLuint texture_switch = 0;
GLuint icon = 0; GLuint icon = 0;
xmb_node_t * node = (xmb_node_t*)menu_list_get_userdata_at_offset(list, i); xmb_node_t * node = (xmb_node_t*)menu_list_get_userdata_at_offset(list, i);
menu_handle_t *menu = menu_driver_get_ptr();
uint32_t hash_label = 0; uint32_t hash_label = 0;
uint32_t hash_value = 0; uint32_t hash_value = 0;
bool do_draw_text = false; bool do_draw_text = false;
*name = *value = 0;
*entry.path = *entry.label = *entry.value = 0;
entry.idx = entry.spacing = entry.type = 0;
if (!node) if (!node)
continue; continue;

View File

@ -252,48 +252,54 @@ static float easing_out_in_bounce(float t, float b, float c, float d)
void menu_animation_free(animation_t *animation) void menu_animation_free(animation_t *animation)
{ {
size_t i; struct tween *t, *tnext;
if (!animation) if (!animation)
return; return;
for (i = 0; i < animation->size; i++) for (t = animation->alive; t; t = tnext)
{ {
if (animation->list[i].subject) tnext = t->next;
animation->list[i].subject = NULL; free(t);
} }
free(animation->list); for (t = animation->dead; t; t = tnext)
{
tnext = t->next;
free(t);
}
animation->alive = NULL;
animation->dead = NULL;
animation->allocated = 0;
free(animation); free(animation);
} }
static struct tween *menu_animation_get_free_slot(animation_t *animation) static struct tween *menu_animation_get_slot(animation_t *animation)
{ {
struct tween *slot = NULL; struct tween *slot = NULL;
unsigned i;
for (i = 0; i < animation->size; ++i) if (!animation->dead)
{ {
if (!animation->list[i].alive) size_t count = ((animation->allocated + 1) * 2) - animation->allocated;
{ unsigned i;
slot = &animation->list[i];
memset(slot, 0, sizeof(*slot));
break;
}
}
if (!slot) for (i = 0; i < count; ++i)
{
if (animation->size >= animation->capacity)
{ {
animation->capacity++; slot = calloc(1, sizeof(struct tween));
animation->list = (struct tween*)realloc(animation->list, slot->next = animation->dead;
animation->capacity * sizeof(struct tween)); animation->dead = slot;
} }
slot = &animation->list[animation->size++]; animation->allocated += count;
} }
slot = animation->dead;
animation->dead = slot->next;
slot->next = animation->alive;
animation->alive = slot;
return slot; return slot;
} }
@ -302,16 +308,30 @@ void menu_animation_kill_by_subject(animation_t *animation, size_t count, const
unsigned i, j; unsigned i, j;
float **sub = (float**)subjects; float **sub = (float**)subjects;
for (i = 0; i < animation->size; ++i) struct tween *t, *tnext, *tprev = NULL;
for (t = animation->alive; t; t = tnext)
{ {
bool killed = false;
tnext = t->next;
for (j = 0; j < count; ++j) for (j = 0; j < count; ++j)
{ {
if (animation->list[i].subject == sub[j]) if (t->subject == sub[j])
{ {
animation->list[i].alive = 0; if (tprev)
animation->list[i].subject = NULL; tprev->next = tnext;
else
animation->alive = tnext;
tnext = t->next;
t->next = animation->dead;
animation->dead = t;
killed = true;
} }
} }
if (!killed)
tprev = t;
} }
} }
@ -319,9 +339,8 @@ bool menu_animation_push(animation_t *animation,
float duration, float target_value, float* subject, float duration, float target_value, float* subject,
enum animation_easing_type easing_enum, tween_cb cb) enum animation_easing_type easing_enum, tween_cb cb)
{ {
struct tween *slot = menu_animation_get_free_slot(animation); struct tween *slot = menu_animation_get_slot(animation);
slot->alive = 1;
slot->duration = duration; slot->duration = duration;
slot->running_since = 0; slot->running_since = 0;
slot->initial_value = *subject; slot->initial_value = *subject;
@ -447,14 +466,13 @@ bool menu_animation_push(animation_t *animation,
} }
static int menu_animation_iterate(struct tween *tween, float dt, static int menu_animation_iterate(struct tween *tween, float dt,
unsigned *active_tweens) unsigned *active_tweens, bool *dead)
{ {
if (!tween) if (!tween)
return -1; return -1;
if (tween->running_since >= tween->duration || !tween->alive) if (tween->running_since >= tween->duration)
{ {
tween->alive = 0; *dead = true;
tween->subject = NULL;
return -1; return -1;
} }
@ -467,9 +485,11 @@ static int menu_animation_iterate(struct tween *tween, float dt,
tween->target_value - tween->initial_value, tween->target_value - tween->initial_value,
tween->duration); tween->duration);
*dead = false;
if (tween->running_since >= tween->duration) if (tween->running_since >= tween->duration)
{ {
*tween->subject = tween->target_value; *tween->subject = tween->target_value;
*dead = true;
if (tween->cb) if (tween->cb)
tween->cb(); tween->cb();
@ -487,15 +507,36 @@ bool menu_animation_update(animation_t *animation, float dt)
unsigned active_tweens = 0; unsigned active_tweens = 0;
menu_handle_t *menu = menu_driver_get_ptr(); menu_handle_t *menu = menu_driver_get_ptr();
for(i = 0; i < animation->size; i++) struct tween *t, *tnext, *tprev = NULL;
menu_animation_iterate(&animation->list[i], dt, &active_tweens);
if (!active_tweens) unsigned active = 0;
for (t = animation->alive; t; t = tnext)
{ {
animation->size = 0; bool dead = false;
return false; tnext = t->next;
menu_animation_iterate(t, dt, &active_tweens, &dead);
if (dead)
{
if (tprev)
tprev->next = tnext;
else
animation->alive = tnext;
t->next = animation->dead;
animation->dead = t;
}
else
{
tprev = t;
active++;
}
} }
if (!animation->alive)
return false;
menu->animation_is_active = true; menu->animation_is_active = true;
return true; return true;

View File

@ -30,7 +30,8 @@ typedef void (*tween_cb) (void);
struct tween struct tween
{ {
int alive; struct tween *next;
float duration; float duration;
float running_since; float running_since;
float initial_value; float initial_value;
@ -42,10 +43,10 @@ struct tween
typedef struct animation typedef struct animation
{ {
struct tween *list; struct tween *alive;
struct tween *dead;
size_t capacity; size_t allocated;
size_t size;
} animation_t; } animation_t;
enum animation_easing_type enum animation_easing_type