mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-11 11:20:12 +00:00
Use aligned allocators for GtkSnapshot
Any data that is later fed to graphene must be allocated with proper alignment, if graphene uses SSE2 or GCC vector instructions. This adds custom array code (a streamlined copy of GArray with all unnecessary bells and whistles removed), which is then used for the state_stack instead of GArray. There's also a runtime check for the size of GtkSnapshotState itself being a multiple of 16. If that is not so, any array elements past the 0th element will lose alignment. There are probably struct attributes that can make GtkSnapshotState always have size that is a multiple of 16, but we'll burn that bridge if we cross it.
This commit is contained in:
parent
a394a86151
commit
c02bc22cc5
@ -24,7 +24,7 @@
|
||||
# define aligned_free(x) free (x)
|
||||
#endif
|
||||
|
||||
/**
|
||||
/*
|
||||
* gsk_aligned_alloc:
|
||||
* @size: the size of the memory to allocate
|
||||
* @number: the multiples of @size to allocate
|
||||
@ -91,7 +91,7 @@ gsk_aligned_alloc (gsize size,
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* gsk_aligned_alloc0:
|
||||
* @size: the size of the memory to allocate
|
||||
* @number: the multiples of @size to allocate
|
||||
@ -117,7 +117,7 @@ gsk_aligned_alloc0 (gsize size,
|
||||
return mem;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* gsk_aligned_free:
|
||||
* @mem: the memory to deallocate
|
||||
*
|
||||
|
@ -31,9 +31,138 @@
|
||||
|
||||
#include "gsk/gskrendernodeprivate.h"
|
||||
|
||||
#include "gsk/gskallocprivate.h"
|
||||
|
||||
#include "gtk/gskpango.h"
|
||||
|
||||
|
||||
static void gtk_snapshot_state_clear (GtkSnapshotState *state);
|
||||
|
||||
/* Returns the smallest power of 2 greater than n, or n if
|
||||
* such power does not fit in a guint
|
||||
*/
|
||||
static guint
|
||||
g_nearest_pow (gint num)
|
||||
{
|
||||
guint n = 1;
|
||||
|
||||
while (n < num && n > 0)
|
||||
n <<= 1;
|
||||
|
||||
return n ? n : num;
|
||||
}
|
||||
|
||||
typedef struct _GtkRealSnapshotStateArray GtkRealSnapshotStateArray;
|
||||
|
||||
struct _GtkRealSnapshotStateArray
|
||||
{
|
||||
GtkSnapshotState *data;
|
||||
guint len;
|
||||
guint alloc;
|
||||
gint ref_count;
|
||||
};
|
||||
|
||||
static GtkSnapshotStateArray*
|
||||
gtk_snapshot_state_array_new (void)
|
||||
{
|
||||
GtkRealSnapshotStateArray *array;
|
||||
|
||||
g_return_val_if_fail (sizeof (GtkSnapshotState) % 16 == 0, NULL);
|
||||
|
||||
array = g_slice_new (GtkRealSnapshotStateArray);
|
||||
|
||||
array->data = NULL;
|
||||
array->len = 0;
|
||||
array->alloc = 0;
|
||||
array->ref_count = 1;
|
||||
|
||||
return (GtkSnapshotStateArray *) array;
|
||||
}
|
||||
|
||||
static GtkSnapshotState *
|
||||
gtk_snapshot_state_array_free (GtkSnapshotStateArray *farray)
|
||||
{
|
||||
GtkRealSnapshotStateArray *array = (GtkRealSnapshotStateArray*) farray;
|
||||
guint i;
|
||||
|
||||
g_return_val_if_fail (array, NULL);
|
||||
|
||||
for (i = 0; i < array->len; i++)
|
||||
gtk_snapshot_state_clear (&array->data[i]);
|
||||
|
||||
gsk_aligned_free (array->data);
|
||||
|
||||
g_slice_free1 (sizeof (GtkRealSnapshotStateArray), array);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define MIN_ARRAY_SIZE 16
|
||||
|
||||
static void
|
||||
gtk_snapshot_state_array_maybe_expand (GtkRealSnapshotStateArray *array,
|
||||
gint len)
|
||||
{
|
||||
guint want_alloc = sizeof (GtkSnapshotState) * (array->len + len);
|
||||
GtkSnapshotState *new_data;
|
||||
|
||||
if (want_alloc <= array->alloc)
|
||||
return;
|
||||
|
||||
want_alloc = g_nearest_pow (want_alloc);
|
||||
want_alloc = MAX (want_alloc, MIN_ARRAY_SIZE);
|
||||
new_data = gsk_aligned_alloc0 (want_alloc, 1, 16);
|
||||
memcpy (new_data, array->data, sizeof (GtkSnapshotState) * array->len);
|
||||
gsk_aligned_free (array->data);
|
||||
array->data = new_data;
|
||||
array->alloc = want_alloc;
|
||||
}
|
||||
|
||||
static GtkSnapshotStateArray*
|
||||
gtk_snapshot_state_array_remove_index (GtkSnapshotStateArray *farray,
|
||||
guint index_)
|
||||
{
|
||||
GtkRealSnapshotStateArray *array = (GtkRealSnapshotStateArray*) farray;
|
||||
|
||||
g_return_val_if_fail (array, NULL);
|
||||
g_return_val_if_fail (index_ < array->len, NULL);
|
||||
|
||||
gtk_snapshot_state_clear (&array->data[index_]);
|
||||
|
||||
memmove (&array->data[index_],
|
||||
&array->data[index_ + 1],
|
||||
(array->len - index_ - 1) * sizeof (GtkSnapshotState));
|
||||
|
||||
array->len -= 1;
|
||||
|
||||
return farray;
|
||||
}
|
||||
|
||||
#define gtk_snapshot_state_array_append_val(a,v) gtk_snapshot_state_array_append_vals (a, &(v), 1)
|
||||
|
||||
static GtkSnapshotStateArray*
|
||||
gtk_snapshot_state_array_append_vals (GtkSnapshotStateArray *farray,
|
||||
gconstpointer data,
|
||||
guint len)
|
||||
{
|
||||
GtkRealSnapshotStateArray *array = (GtkRealSnapshotStateArray*) farray;
|
||||
|
||||
g_return_val_if_fail (array, NULL);
|
||||
|
||||
if (len == 0)
|
||||
return farray;
|
||||
|
||||
gtk_snapshot_state_array_maybe_expand (array, len);
|
||||
|
||||
memcpy (&array->data[array->len], data,
|
||||
sizeof (GtkSnapshotState) * len);
|
||||
|
||||
array->len += len;
|
||||
|
||||
return farray;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* SECTION:gtksnapshot
|
||||
* @Short_description: Auxiliary object for snapshots
|
||||
@ -120,9 +249,9 @@ gtk_snapshot_push_state (GtkSnapshot *snapshot,
|
||||
state.start_node_index = snapshot->nodes->len;
|
||||
state.n_nodes = 0;
|
||||
|
||||
g_array_append_val (snapshot->state_stack, state);
|
||||
gtk_snapshot_state_array_append_val (snapshot->state_stack, state);
|
||||
|
||||
return &g_array_index (snapshot->state_stack, GtkSnapshotState, snapshot->state_stack->len - 1);
|
||||
return &snapshot->state_stack->data[snapshot->state_stack->len - 1];
|
||||
}
|
||||
|
||||
static GtkSnapshotState *
|
||||
@ -130,7 +259,7 @@ gtk_snapshot_get_current_state (const GtkSnapshot *snapshot)
|
||||
{
|
||||
g_assert (snapshot->state_stack->len > 0);
|
||||
|
||||
return &g_array_index (snapshot->state_stack, GtkSnapshotState, snapshot->state_stack->len - 1);
|
||||
return &snapshot->state_stack->data[snapshot->state_stack->len - 1];
|
||||
}
|
||||
|
||||
static GtkSnapshotState *
|
||||
@ -138,7 +267,7 @@ gtk_snapshot_get_previous_state (const GtkSnapshot *snapshot)
|
||||
{
|
||||
g_assert (snapshot->state_stack->len > 1);
|
||||
|
||||
return &g_array_index (snapshot->state_stack, GtkSnapshotState, snapshot->state_stack->len - 2);
|
||||
return &snapshot->state_stack->data[snapshot->state_stack->len - 2];
|
||||
}
|
||||
|
||||
static void
|
||||
@ -160,8 +289,7 @@ gtk_snapshot_new (void)
|
||||
|
||||
snapshot = g_object_new (GTK_TYPE_SNAPSHOT, NULL);
|
||||
|
||||
snapshot->state_stack = g_array_new (FALSE, TRUE, sizeof (GtkSnapshotState));
|
||||
g_array_set_clear_func (snapshot->state_stack, (GDestroyNotify)gtk_snapshot_state_clear);
|
||||
snapshot->state_stack = gtk_snapshot_state_array_new ();
|
||||
snapshot->nodes = g_ptr_array_new_with_free_func ((GDestroyNotify)gsk_render_node_unref);
|
||||
|
||||
gtk_snapshot_push_state (snapshot,
|
||||
@ -925,7 +1053,7 @@ gtk_snapshot_pop_internal (GtkSnapshot *snapshot)
|
||||
snapshot->nodes->len - state->n_nodes,
|
||||
state->n_nodes);
|
||||
|
||||
g_array_remove_index (snapshot->state_stack, state_index);
|
||||
gtk_snapshot_state_array_remove_index (snapshot->state_stack, state_index);
|
||||
|
||||
return node;
|
||||
}
|
||||
@ -955,7 +1083,7 @@ gtk_snapshot_to_node (GtkSnapshot *snapshot)
|
||||
|
||||
result = gtk_snapshot_pop_internal (snapshot);
|
||||
|
||||
g_array_free (snapshot->state_stack, TRUE);
|
||||
gtk_snapshot_state_array_free (snapshot->state_stack);
|
||||
snapshot->state_stack = NULL;
|
||||
|
||||
g_ptr_array_free (snapshot->nodes, TRUE);
|
||||
|
@ -23,6 +23,17 @@
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GtkSnapshotState GtkSnapshotState;
|
||||
typedef struct _GtkSnapshotStateArray GtkSnapshotStateArray;
|
||||
|
||||
/* This is a stripped-down copy of GArray tailored specifically
|
||||
* for GtkSnapshotState and guaranteed to be aligned to 16 byte
|
||||
* bounaries.
|
||||
*/
|
||||
struct _GtkSnapshotStateArray
|
||||
{
|
||||
GtkSnapshotState *data;
|
||||
guint len;
|
||||
};
|
||||
|
||||
typedef GskRenderNode * (* GtkSnapshotCollectFunc) (GtkSnapshot *snapshot,
|
||||
GtkSnapshotState *state,
|
||||
@ -88,7 +99,7 @@ struct _GtkSnapshotState {
|
||||
struct _GdkSnapshot {
|
||||
GObject parent_instance; /* it's really GdkSnapshot, but don't tell anyone! */
|
||||
|
||||
GArray *state_stack;
|
||||
GtkSnapshotStateArray *state_stack;
|
||||
GPtrArray *nodes;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user