[cogl/wip/neil/pipeline-uniforms: 15/17] Stash
- From: Neil Roberts <nroberts src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [cogl/wip/neil/pipeline-uniforms: 15/17] Stash
- Date: Wed, 2 Nov 2011 14:06:12 +0000 (UTC)
commit 683cebe22e66e7f5a7eb82b5688f4c2fb2a22c2f
Author: Neil Roberts <neil linux intel com>
Date: Tue Nov 1 11:49:56 2011 +0000
Stash
cogl/cogl-bitmask.c | 11 ++
cogl/cogl-bitmask.h | 14 ++-
cogl/cogl-context-private.h | 3 +-
cogl/cogl-context.c | 11 +--
cogl/cogl-pipeline-private.h | 7 --
cogl/cogl-pipeline-progend-glsl.c | 187 ++++++++++++++++++++++++++++++++-----
cogl/cogl-pipeline-state.c | 15 +--
cogl/cogl-pipeline.c | 21 ++--
8 files changed, 205 insertions(+), 64 deletions(-)
---
diff --git a/cogl/cogl-bitmask.c b/cogl/cogl-bitmask.c
index abac435..90f3436 100644
--- a/cogl/cogl-bitmask.c
+++ b/cogl/cogl-bitmask.c
@@ -273,3 +273,14 @@ _cogl_bitmask_is_empty_array (const CoglBitmask *bitmask)
return TRUE;
}
+
+void
+_cogl_bitmask_set_flags_array (const CoglBitmask *bitmask,
+ unsigned long *flags)
+{
+ const GArray *array = (const GArray *) *bitmask;
+ int i;
+
+ for (i = 0; i < array->len; i++)
+ flags[i] |= g_array_index (array, unsigned long, i);
+}
diff --git a/cogl/cogl-bitmask.h b/cogl/cogl-bitmask.h
index a1710af..e44f2a2 100644
--- a/cogl/cogl-bitmask.h
+++ b/cogl/cogl-bitmask.h
@@ -104,6 +104,10 @@ _cogl_bitmask_clear_all_in_array (CoglBitmask *bitmask);
gboolean
_cogl_bitmask_is_empty_array (const CoglBitmask *bitmask);
+void
+_cogl_bitmask_set_flags_array (const CoglBitmask *bitmask,
+ unsigned long *flags);
+
/*
* cogl_bitmask_set_bits:
* @dst: The bitmask to modify
@@ -254,22 +258,20 @@ _cogl_bitmask_is_empty (const CoglBitmask *bitmask)
/*
* _cogl_bitmask_set_flags:
* @bitmask: A pointer to a bitmask
- * @flags: An array of unsigned ints
+ * @flags: An array of flags
*
- * This or's the bits from @bitmask into the flags array (see
+ * Bitwise or's the bits from @bitmask into the flags array (see
* cogl-flags) pointed to by @flags.
*/
-#if 0
static inline void
_cogl_bitmask_set_flags (const CoglBitmask *bitmask,
- unsigned int *flags)
+ unsigned long *flags)
{
if (_cogl_bitmask_has_array (bitmask))
return _cogl_bitmask_set_flags_array (bitmask, flags);
else
- flags[0] |= _cogl_bitmask
+ flags[0] |= _cogl_bitmask_to_bits (bitmask);
}
-#endif
G_END_DECLS
diff --git a/cogl/cogl-context-private.h b/cogl/cogl-context-private.h
index 97f8757..8125e7b 100644
--- a/cogl/cogl-context-private.h
+++ b/cogl/cogl-context-private.h
@@ -263,7 +263,8 @@ struct _CoglContext
they increase sequentially so that we can use the id as an index
into a bitfield representing the uniforms that a pipeline
overrides from its parent */
- GHashTable *uniform_names;
+ GSList *uniform_names;
+ int n_uniform_names;
/* This defines a list of function pointers that Cogl uses from
either GL or GLES. All functions are accessed indirectly through
diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c
index 9058625..a972ee2 100644
--- a/cogl/cogl-context.c
+++ b/cogl/cogl-context.c
@@ -221,12 +221,8 @@ cogl_context_new (CoglDisplay *display,
g_assert_not_reached ();
}
- /* We don't need a destructor for the uniform name string because
- it is contained within the allocation of the struct */
- context->uniform_names = g_hash_table_new_full (g_str_hash,
- g_str_equal,
- NULL,
- g_free);
+ context->uniform_names = NULL;
+ context->n_uniform_names = 0;
/* Initialise the driver specific state */
_cogl_init_feature_overrides (context);
@@ -493,7 +489,8 @@ _cogl_context_free (CoglContext *context)
cogl_pipeline_cache_free (context->pipeline_cache);
- g_hash_table_destroy (context->uniform_names);
+ g_slist_foreach (context->uniform_names, (GFunc) g_free, NULL);
+ g_slist_free (context->uniform_names);
g_byte_array_free (context->buffer_map_fallback_array, TRUE);
diff --git a/cogl/cogl-pipeline-private.h b/cogl/cogl-pipeline-private.h
index c9e91bc..4f28840 100644
--- a/cogl/cogl-pipeline-private.h
+++ b/cogl/cogl-pipeline-private.h
@@ -414,13 +414,6 @@ typedef struct _CoglPipelineHashState
unsigned int hash;
} CoglPipelineHashState;
-typedef struct _CoglPipelineUniformName
-{
- int index;
- /* Overallocated to store the name in this struct */
- char name[1];
-} CoglPipelineUniformName;
-
/*
* CoglPipelineDestroyCallback
* @pipeline: The #CoglPipeline that has been destroyed
diff --git a/cogl/cogl-pipeline-progend-glsl.c b/cogl/cogl-pipeline-progend-glsl.c
index 9cda3c7..4ec6f37 100644
--- a/cogl/cogl-pipeline-progend-glsl.c
+++ b/cogl/cogl-pipeline-progend-glsl.c
@@ -29,6 +29,8 @@
#include "config.h"
#endif
+#include <string.h>
+
#include "cogl-util.h"
#include "cogl-context-private.h"
#include "cogl-pipeline-private.h"
@@ -165,6 +167,7 @@ get_program_state (CoglPipeline *pipeline)
#ifdef HAVE_COGL_GLES2
#define ATTRIBUTE_LOCATION_UNKNOWN -2
+#define UNIFORM_LOCATION_UNKNOWN -2
/* Under GLES2 the vertex attribute API needs to query the attribute
numbers because it can't used the fixed function API to set the
@@ -566,16 +569,127 @@ get_ancestors (CoglPipeline *pipeline)
return ancestors;
}
+static void
+flush_uniform_boxed_value (CoglContext *ctx,
+ GLint uniform_location,
+ const CoglBoxedValue *value)
+{
+ switch (value->type)
+ {
+ case COGL_BOXED_FLOAT:
+ {
+ const float *array;
+
+ if (value->count > 1)
+ array = value->v.float_array;
+ else
+ array = value->v.float_value;
+
+ switch (value->size)
+ {
+ case 1:
+ ctx->glUniform1fv (uniform_location,
+ value->count,
+ array);
+ break;
+
+ case 2:
+ ctx->glUniform2fv (uniform_location,
+ value->count,
+ array);
+ break;
+
+ case 3:
+ ctx->glUniform3fv (uniform_location,
+ value->count,
+ array);
+ break;
+
+ case 4:
+ ctx->glUniform4fv (uniform_location,
+ value->count,
+ array);
+ break;
+ }
+
+ break;
+
+ /* FIXME: add more types... */
+ }
+ }
+}
+
typedef struct
{
- CoglProgramState *program_state;
+ CoglPipelineProgramState *program_state;
CoglPipeline *flushed_ancestor;
- unsigned int *force_flush_uniforms;
- unsigned int *flushed_uniforms;
- const CoglPipelineUniformsState *uniforms_state;
- int uniforms_count;
+ unsigned long *force_flush_uniforms;
+ unsigned long *flushed_uniforms;
+ CoglPipelineUniformsState *uniforms_state;
+ gboolean found_ancestor;
+ CoglContext *ctx;
+ CoglPipelineUniformOverride *override;
} FlushUniformsClosure;
+static gboolean
+flush_uniform_cb (int uniform_num, void *user_data)
+{
+ FlushUniformsClosure *data = user_data;
+
+ if (!COGL_FLAGS_GET (data->flushed_uniforms, uniform_num) &&
+ (!data->found_ancestor ||
+ COGL_FLAGS_GET (data->force_flush_uniforms, uniform_num)))
+ {
+ GArray *uniform_locations;
+ GLint uniform_location;
+
+ if (data->program_state->uniform_locations == NULL)
+ data->program_state->uniform_locations =
+ g_array_new (FALSE, FALSE, sizeof (GLint));
+
+ uniform_locations = data->program_state->uniform_locations;
+
+ if (uniform_locations->len <= uniform_num)
+ {
+ unsigned int old_len = uniform_locations->len;
+
+ g_array_set_size (uniform_locations, uniform_num + 1);
+
+ while (old_len <= uniform_num)
+ {
+ g_array_index (uniform_locations, GLint, old_len) =
+ UNIFORM_LOCATION_UNKNOWN;
+ old_len++;
+ }
+ }
+
+ uniform_location = g_array_index (uniform_locations, GLint, uniform_num);
+
+ if (uniform_location == UNIFORM_LOCATION_UNKNOWN)
+ {
+ const char *uniform_name =
+ g_slist_nth (data->ctx->uniform_names, uniform_num)->data;
+
+ uniform_location =
+ data->ctx->glGetUniformLocation (data->program_state->program,
+ uniform_name);
+ g_array_index (uniform_locations, GLint, uniform_num) =
+ uniform_location;
+ }
+
+ if (uniform_location != -1)
+ flush_uniform_boxed_value (data->ctx,
+ uniform_location,
+ &data->override->value);
+
+ COGL_FLAGS_SET (data->flushed_uniforms, uniform_num, TRUE);
+ }
+
+ data->override = COGL_SLIST_NEXT (data->override, list_node);
+
+ return TRUE;
+}
+
static void
_cogl_pipeline_progend_glsl_flush_uniforms (CoglPipeline *pipeline,
CoglPipelineProgramState *
@@ -584,23 +698,29 @@ _cogl_pipeline_progend_glsl_flush_uniforms (CoglPipeline *pipeline,
gboolean program_changed)
{
FlushUniformsClosure data;
- int uniforms_count;
+ int n_uniform_longs;
+
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
_cogl_bitmask_init (&data.force_flush_uniforms);
if (pipeline->differences & COGL_PIPELINE_STATE_UNIFORMS)
- data.uniforms_state = &pipeline->big_state->data.uniforms_state;
+ data.uniforms_state = &pipeline->big_state->uniforms_state;
else
data.uniforms_state = NULL;
data.flushed_ancestor = NULL;
- data.uniforms_count = g_hash_table_size (ctx->uniform_names);
- data.force_flush_uniforms = g_newa (unsigned int, data.uniforms_count);
+ data.program_state = program_state;
+ data.ctx = ctx;
+
+ n_uniform_longs = COGL_FLAGS_N_LONGS_FOR_SIZE (ctx->n_uniform_names);
+
+ data.force_flush_uniforms = g_newa (unsigned long, n_uniform_longs);
memset (data.force_flush_uniforms, 0,
- sizeof (unsigned int) * data.uniforms_count);
- data.flushed_uniforms = g_newa (unsigned int, data.uniforms_count);
- memset (data.data.flushed_uniforms, 0,
- sizeof (unsigned int) * data.uniforms_count);
+ n_uniform_longs * sizeof (unsigned long));
+ data.flushed_uniforms = g_newa (unsigned long, n_uniform_longs);
+ memset (data.flushed_uniforms, 0,
+ n_uniform_longs * sizeof (unsigned long));
/* Try to find a common ancestor for the values that were already
flushed on the pipeline that this program state was last used for
@@ -633,26 +753,49 @@ _cogl_pipeline_progend_glsl_flush_uniforms (CoglPipeline *pipeline,
/* We need to be sure to flush any uniforms that have changed
since the last flush */
if (data.uniforms_state)
- _cogl_bitmask_set_bits (&data.force_flush_uniforms,
- &data.uniforms_state->changed_mask);
+ _cogl_bitmask_set_flags (&data.uniforms_state->changed_mask,
+ data.force_flush_uniforms);
/* We need to flush any uniforms that are children of the common
ancestor up to the last used pipeline */
while (a)
{
CoglPipeline *child_pipeline = a->data;
- const CoglPipelineUniformsState *data.uniforms_state =
- &child_pipeline->big_state->data.uniforms_state;
- _cogl_bitmask_set_bits (&data.force_flush_uniforms,
- &data.uniforms_state->override_mask);
+ if (pipeline->differences & COGL_PIPELINE_STATE_UNIFORMS)
+ {
+ const CoglPipelineUniformsState *uniforms_state =
+ &child_pipeline->big_state->uniforms_state;
+ _cogl_bitmask_set_flags (&uniforms_state->override_mask,
+ data.force_flush_uniforms);
+ }
a = a->next;
}
}
- if (data.uniforms_state)
- _cogl_bitmask_clear (&data.uniforms_state->changed_mask);
+ data.found_ancestor = FALSE;
+
+ while (pipeline)
+ {
+ if (pipeline == data.flushed_ancestor)
+ data.found_ancestor = TRUE;
+
+ if (pipeline->differences & COGL_PIPELINE_STATE_UNIFORMS)
+ {
+ const CoglPipelineUniformsState *uniforms_state =
+ &pipeline->big_state->uniforms_state;
+
+ data.override = COGL_SLIST_FIRST (&uniforms_state->override_list);
+
+ _cogl_bitmask_foreach (&uniforms_state->override_mask,
+ flush_uniform_cb,
+ &data);
+ }
- _cogl_bitmask_destroy (&data.force_flush_uniforms);
+ pipeline = _cogl_pipeline_get_parent (pipeline);
+ }
+
+ if (data.uniforms_state)
+ _cogl_bitmask_clear_all (&data.uniforms_state->changed_mask);
}
static void
diff --git a/cogl/cogl-pipeline-state.c b/cogl/cogl-pipeline-state.c
index e1c2a49..cb91335 100644
--- a/cogl/cogl-pipeline-state.c
+++ b/cogl/cogl-pipeline-state.c
@@ -266,8 +266,7 @@ _cogl_pipeline_get_all_uniform_values (CoglPipeline *pipeline,
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
memset (values, 0,
- sizeof (const CoglBoxedValue *) *
- g_hash_table_size (ctx->uniform_names));
+ sizeof (const CoglBoxedValue *) * ctx->n_uniform_names);
data.values = values;
@@ -293,7 +292,6 @@ _cogl_pipeline_uniforms_state_equal (CoglPipeline *authority0,
CoglPipeline *authority1)
{
const CoglBoxedValue **values0, **values1;
- int n_uniform_names;
int i;
_COGL_GET_CONTEXT (ctx, FALSE);
@@ -301,15 +299,13 @@ _cogl_pipeline_uniforms_state_equal (CoglPipeline *authority0,
if (authority0 == authority1)
return TRUE;
- n_uniform_names = g_hash_table_size (ctx->uniform_names);
-
- values0 = g_alloca (sizeof (const CoglBoxedValue *) * n_uniform_names);
- values1 = g_alloca (sizeof (const CoglBoxedValue *) * n_uniform_names);
+ values0 = g_alloca (sizeof (const CoglBoxedValue *) * ctx->n_uniform_names);
+ values1 = g_alloca (sizeof (const CoglBoxedValue *) * ctx->n_uniform_names);
_cogl_pipeline_get_all_uniform_values (authority0, values0);
_cogl_pipeline_get_all_uniform_values (authority1, values1);
- for (i = 0; i < n_uniform_names; i++)
+ for (i = 0; i < ctx->n_uniform_names; i++)
{
const CoglBoxedValue *value0 = values0[i];
const CoglBoxedValue *value1 = values1[i];
@@ -1393,8 +1389,7 @@ _cogl_pipeline_override_uniform (CoglPipeline *pipeline,
g_return_val_if_fail (cogl_is_pipeline (pipeline), NULL);
g_return_val_if_fail (location >= 0, NULL);
- g_return_val_if_fail (location < g_hash_table_size (ctx->uniform_names),
- NULL);
+ g_return_val_if_fail (location < ctx->n_uniform_names, NULL);
/* - Flush journal primitives referencing the current state.
* - Make sure the pipeline has no dependants so it may be modified.
diff --git a/cogl/cogl-pipeline.c b/cogl/cogl-pipeline.c
index ba79aad..3d2bf3e 100644
--- a/cogl/cogl-pipeline.c
+++ b/cogl/cogl-pipeline.c
@@ -2847,8 +2847,7 @@ int
cogl_pipeline_get_uniform_location (CoglPipeline *pipeline,
const char *uniform_name)
{
- CoglPipelineUniformName *name_node;
- int name_len;
+ GSList *l;
int location = 0;
_COGL_GET_CONTEXT (ctx, -1);
@@ -2861,16 +2860,16 @@ cogl_pipeline_get_uniform_location (CoglPipeline *pipeline,
be. */
/* Look for an existing uniform with this name */
- name_node = g_hash_table_lookup (ctx->uniform_names, uniform_name);
- if (name_node)
- return name_node->index;
+ for (l = ctx->uniform_names; l; l = l->next)
+ {
+ if (!strcmp (uniform_name, l->data))
+ return location;
- name_len = strlen (uniform_name);
- name_node = g_malloc (sizeof (CoglPipelineUniformName) + name_len);
- name_node->index = g_hash_table_size (ctx->uniform_names);
- memcpy (name_node->name, uniform_name, name_len + 1);
+ location++;
+ }
- g_hash_table_insert (ctx->uniform_names, name_node->name, name_node);
+ ctx->uniform_names =
+ g_slist_append (ctx->uniform_names, g_strdup (uniform_name));
- return location;
+ return ctx->n_uniform_names++;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]