[cogl/wip/neil/pipeline-uniforms: 7/9] Stash
- From: Neil Roberts <nroberts src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [cogl/wip/neil/pipeline-uniforms: 7/9] Stash
- Date: Fri, 28 Oct 2011 19:13:58 +0000 (UTC)
commit 8782a27af4689222ba59f61daf116a37fdc7fb5f
Author: Neil Roberts <neil linux intel com>
Date: Wed Oct 26 18:55:15 2011 +0100
Stash
cogl/cogl-context-private.h | 7 +++++
cogl/cogl-context.c | 4 +++
cogl/cogl-pipeline-private.h | 42 +++++++++++++++++++++++++++-
cogl/cogl-pipeline-state.c | 60 +++++++++++++++++++++++++++++++++++++++++
cogl/cogl-pipeline.c | 61 ++++++++++++++++++++++++++++++++++++++++++
5 files changed, 172 insertions(+), 2 deletions(-)
---
diff --git a/cogl/cogl-context-private.h b/cogl/cogl-context-private.h
index 3981f7b..d7ff7e3 100644
--- a/cogl/cogl-context-private.h
+++ b/cogl/cogl-context-private.h
@@ -257,6 +257,13 @@ struct _CoglContext
[COGL_FLAGS_N_INTS_FOR_SIZE (COGL_WINSYS_FEATURE_N_FEATURES)];
void *winsys;
+ /* List of names of uniforms. These are used like quarks to give a
+ unique number to each uniform name except that we ensure that
+ 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;
+
/* This defines a list of function pointers that Cogl uses from
either GL or GLES. All functions are accessed indirectly through
these pointers rather than linking to them directly */
diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c
index e16957d..1a8f907 100644
--- a/cogl/cogl-context.c
+++ b/cogl/cogl-context.c
@@ -204,6 +204,8 @@ cogl_context_new (CoglDisplay *display,
g_assert_not_reached ();
}
+ context->uniform_names = NULL;
+
/* Initialise the driver specific state */
_cogl_init_feature_overrides (context);
@@ -469,6 +471,8 @@ _cogl_context_free (CoglContext *context)
cogl_pipeline_cache_free (context->pipeline_cache);
+ g_hash_table_destroy (context->uniform_names);
+
g_byte_array_free (context->buffer_map_fallback_array, TRUE);
cogl_object_unref (context->display);
diff --git a/cogl/cogl-pipeline-private.h b/cogl/cogl-pipeline-private.h
index d6c0dcc..eaf807f 100644
--- a/cogl/cogl-pipeline-private.h
+++ b/cogl/cogl-pipeline-private.h
@@ -167,6 +167,7 @@ typedef enum
COGL_PIPELINE_STATE_POINT_SIZE_INDEX,
COGL_PIPELINE_STATE_LOGIC_OPS_INDEX,
COGL_PIPELINE_STATE_CULL_FACE_INDEX,
+ COGL_PIPELINE_STATE_UNIFORMS_INDEX,
/* non-sparse */
COGL_PIPELINE_STATE_REAL_BLEND_ENABLE_INDEX,
@@ -214,6 +215,8 @@ typedef enum _CoglPipelineState
1L<<COGL_PIPELINE_STATE_LOGIC_OPS_INDEX,
COGL_PIPELINE_STATE_CULL_FACE =
1L<<COGL_PIPELINE_STATE_CULL_FACE_INDEX,
+ COGL_PIPELINE_STATE_UNIFORMS =
+ 1L<<COGL_PIPELINE_STATE_UNIFORMS_INDEX,
COGL_PIPELINE_STATE_REAL_BLEND_ENABLE =
1L<<COGL_PIPELINE_STATE_REAL_BLEND_ENABLE_INDEX,
@@ -249,7 +252,8 @@ typedef enum _CoglPipelineState
COGL_PIPELINE_STATE_FOG | \
COGL_PIPELINE_STATE_POINT_SIZE | \
COGL_PIPELINE_STATE_LOGIC_OPS | \
- COGL_PIPELINE_STATE_CULL_FACE)
+ COGL_PIPELINE_STATE_CULL_FACE | \
+ COGL_PIPELINE_STATE_UNIFORMS)
#define COGL_PIPELINE_STATE_MULTI_PROPERTY \
(COGL_PIPELINE_STATE_LAYERS | \
@@ -258,7 +262,8 @@ typedef enum _CoglPipelineState
COGL_PIPELINE_STATE_DEPTH | \
COGL_PIPELINE_STATE_FOG | \
COGL_PIPELINE_STATE_LOGIC_OPS | \
- COGL_PIPELINE_STATE_CULL_FACE)
+ COGL_PIPELINE_STATE_CULL_FACE | \
+ COGL_PIPELINE_STATE_UNIFORMS)
#define COGL_PIPELINE_STATE_AFFECTS_VERTEX_CODEGEN \
(COGL_PIPELINE_STATE_LAYERS | \
@@ -348,6 +353,31 @@ typedef struct
CoglWinding front_winding;
} CoglPipelineCullFaceState;
+typedef struct _CoglPipelineUniformOverride CoglPipelineUniformOverride;
+
+COGL_SLIST_HEAD (CoglPipelineUniformOverrideList,
+ CoglPipelineUniformOverride);
+
+struct _CoglPipelineUniformOverride
+{
+ COGL_SLIST_ENTRY (CoglPipelineUniformOverride) list_node;
+
+ /* We don't need to store the location of the uniform here because
+ it is implicit from the order in the list */
+
+ /* One of these overrides can effectively remove a uniform by
+ setting the boxed value type to none. In that case no attempt
+ will be made to upload the value */
+
+ CoglBoxedValue value;
+};
+
+typedef struct
+{
+ CoglBitmask override_mask;
+ CoglPipelineUniformOverrideList override_list;
+} CoglPipelineUniformsState;
+
typedef struct
{
CoglPipelineLightingState lighting_state;
@@ -359,6 +389,7 @@ typedef struct
float point_size;
CoglPipelineLogicOpsState logic_ops_state;
CoglPipelineCullFaceState cull_face_state;
+ CoglPipelineUniformsState uniforms_state;
} CoglPipelineBigState;
typedef enum
@@ -380,6 +411,13 @@ 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-state.c b/cogl/cogl-pipeline-state.c
index 45beb75..5270756 100644
--- a/cogl/cogl-pipeline-state.c
+++ b/cogl/cogl-pipeline-state.c
@@ -1455,3 +1455,63 @@ _cogl_pipeline_hash_cull_face_state (CoglPipeline *authority,
cull_face_state,
sizeof (CoglPipelineCullFaceState));
}
+
+static void
+cogl_pipeline_set_uniform_x (CoglPipeline *pipeline,
+ int location,
+ int size,
+ int count,
+ CoglBoxedType type,
+ gsize value_size,
+ gconstpointer value,
+ gboolean transpose)
+{
+ CoglPipelineUniformOverride *previous_override = NULL;
+ CoglPipelineUniformOverride *override = NULL;
+
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ g_return_if_fail (cogl_is_pipeline (pipeline));
+ g_return_if_fail (location >= 0);
+ g_return_if_fail (location < g_hash_table_size (ctx->uniform_names));
+ g_return_if_fail (size >= 1 && size <= 4 && count >= 1);
+#if 0
+ if (uniform_no >= 0 && uniform_no < program->custom_uniforms->len &&
+ size >= 1 && size <= 4 && count >= 1)
+ {
+ CoglProgramUniform *uniform =
+ &g_array_index (program->custom_uniforms,
+ CoglProgramUniform, uniform_no);
+
+ if (count == 1)
+ {
+ if (uniform->value.count > 1)
+ g_free (uniform->value.v.array);
+
+ memcpy (uniform->value.v.float_value, value, value_size);
+ }
+ else
+ {
+ if (uniform->value.count > 1)
+ {
+ if (uniform->value.count != count ||
+ uniform->value.size != size ||
+ uniform->value.type != type)
+ {
+ g_free (uniform->value.v.array);
+ uniform->value.v.array = g_malloc (count * value_size);
+ }
+ }
+ else
+ uniform->value.v.array = g_malloc (count * value_size);
+
+ memcpy (uniform->value.v.array, value, count * value_size);
+ }
+
+ uniform->value.type = type;
+ uniform->value.size = size;
+ uniform->value.count = count;
+ uniform->dirty = TRUE;
+ }
+#endif
+}
diff --git a/cogl/cogl-pipeline.c b/cogl/cogl-pipeline.c
index 0af7014..9f755aa 100644
--- a/cogl/cogl-pipeline.c
+++ b/cogl/cogl-pipeline.c
@@ -458,6 +458,25 @@ _cogl_pipeline_free (CoglPipeline *pipeline)
pipeline->big_state->user_program)
cogl_handle_unref (pipeline->big_state->user_program);
+ if (pipeline->differences & COGL_PIPELINE_STATE_UNIFORMS)
+ {
+ CoglPipelineUniformsState *uniforms_state
+ = &pipeline->big_state->uniforms_state;
+ CoglPipelineUniformOverride *override, *tmp;
+
+ COGL_SLIST_FOREACH_SAFE (override,
+ &uniforms_state->override_list,
+ list_node,
+ tmp)
+ {
+ if (override->value.count > 1)
+ g_free (override->value.v.array);
+ g_free (override);
+ }
+
+ _cogl_bitmask_destroy (&uniforms_state->override_mask);
+ }
+
if (pipeline->differences & COGL_PIPELINE_STATE_NEEDS_BIG_STATE)
g_slice_free (CoglPipelineBigState, pipeline->big_state);
@@ -2808,3 +2827,45 @@ _cogl_pipeline_get_state_for_fragment_codegen (CoglContext *context)
return state;
}
+
+int
+cogl_pipeline_get_uniform_location (CoglPipeline *pipeline,
+ const char *uniform_name)
+{
+ CoglPipelineUniformName *name_node;
+ int name_len;
+ int location = 0;
+
+ _COGL_GET_CONTEXT (ctx, -1);
+
+ /* This API is designed as if the uniform locations are specific to
+ a pipeline but they are actually unique across a whole
+ CoglContext. Potentially this could just be
+ cogl_context_get_uniform_location but it seems to make sense to
+ keep the API this way so that we can change the internals if need
+ be. */
+
+ /* Look for an existing uniform with this name */
+ if (ctx->uniform_names)
+ {
+ name_node = g_hash_table_lookup (ctx->uniform_names, uniform_name);
+ if (name_node)
+ return name_node->index;
+ }
+ else
+ /* We don't need a destructor for the uniform name string because
+ it is contained within the allocation of the struct */
+ ctx->uniform_names = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ NULL,
+ g_free);
+
+ 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);
+
+ g_hash_table_insert (ctx->uniform_names, name_node->name, name_node);
+
+ return location;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]