diff --git a/cogl/cogl/cogl-pipeline-layer-state.c b/cogl/cogl/cogl-pipeline-layer-state.c index 88a6dc8ab..4d1a3e7a0 100644 --- a/cogl/cogl/cogl-pipeline-layer-state.c +++ b/cogl/cogl/cogl-pipeline-layer-state.c @@ -623,6 +623,8 @@ _cogl_pipeline_layer_add_vertex_snippet (CoglPipeline *pipeline, _cogl_pipeline_snippet_list_add (&layer->big_state->vertex_snippets, snippet); + cogl_pipeline_add_capability_from_snippet (pipeline, snippet); + /* If we weren't previously the authority on this state then we need * to extended our differences mask and so it's possible that some * of our ancestry will now become redundant, so we aim to reparent @@ -659,6 +661,8 @@ _cogl_pipeline_layer_add_fragment_snippet (CoglPipeline *pipeline, _cogl_pipeline_snippet_list_add (&layer->big_state->fragment_snippets, snippet); + cogl_pipeline_add_capability_from_snippet (pipeline, snippet); + /* If we weren't previously the authority on this state then we need * to extended our differences mask and so it's possible that some * of our ancestry will now become redundant, so we aim to reparent diff --git a/cogl/cogl/cogl-pipeline-private.h b/cogl/cogl/cogl-pipeline-private.h index f36cba22d..82c9c4bb6 100644 --- a/cogl/cogl/cogl-pipeline-private.h +++ b/cogl/cogl/cogl-pipeline-private.h @@ -323,6 +323,10 @@ struct _CoglPipeline * and corresponding authorities_cache_dirty:1 bitfield */ + /* Array of opaque capabilities tagged by owners of pipelines. + */ + GArray *capabilities; + /* bitfields */ /* Weak pipelines don't count as dependants on their parents which @@ -783,3 +787,7 @@ _cogl_pipeline_get_layer_state_for_fragment_codegen (CoglContext *context); CoglPipelineState _cogl_pipeline_get_state_for_fragment_codegen (CoglContext *context); + +void +cogl_pipeline_add_capability_from_snippet (CoglPipeline *pipeline, + CoglSnippet *snippet); diff --git a/cogl/cogl/cogl-pipeline-state.c b/cogl/cogl/cogl-pipeline-state.c index 102cf922e..3caf6f922 100644 --- a/cogl/cogl/cogl-pipeline-state.c +++ b/cogl/cogl/cogl-pipeline-state.c @@ -1146,6 +1146,8 @@ _cogl_pipeline_add_vertex_snippet (CoglPipeline *pipeline, _cogl_pipeline_snippet_list_add (&pipeline->big_state->vertex_snippets, snippet); + + cogl_pipeline_add_capability_from_snippet (pipeline, snippet); } static void @@ -1163,6 +1165,8 @@ _cogl_pipeline_add_fragment_snippet (CoglPipeline *pipeline, _cogl_pipeline_snippet_list_add (&pipeline->big_state->fragment_snippets, snippet); + + cogl_pipeline_add_capability_from_snippet (pipeline, snippet); } void diff --git a/cogl/cogl/cogl-pipeline.c b/cogl/cogl/cogl-pipeline.c index fcd2580d5..43e665533 100644 --- a/cogl/cogl/cogl-pipeline.c +++ b/cogl/cogl/cogl-pipeline.c @@ -45,6 +45,7 @@ #include "cogl/cogl-util.h" #include "cogl/cogl-profile.h" #include "cogl/cogl-depth-state-private.h" +#include "cogl/cogl-snippet-private.h" #include "cogl/cogl1-context.h" #include @@ -154,6 +155,8 @@ cogl_pipeline_dispose (GObject *object) recursively_free_layer_caches (pipeline); + g_clear_pointer (&pipeline->capabilities, g_array_unref); + G_OBJECT_CLASS (cogl_pipeline_parent_class)->dispose (object); } @@ -329,6 +332,9 @@ _cogl_pipeline_copy (CoglPipeline *src, gboolean is_weak) pipeline->dirty_real_blend_enable = src->dirty_real_blend_enable; pipeline->unknown_color_alpha = src->unknown_color_alpha; + if (src->capabilities) + pipeline->capabilities = g_array_copy (src->capabilities); + /* XXX: * consider generalizing the idea of "cached" properties. These * would still have an authority like other sparse properties but @@ -2792,3 +2798,60 @@ cogl_pipeline_get_uniform_location (CoglPipeline *pipeline, return ctx->n_uniform_names++; } + +typedef struct +{ + GQuark domain; + unsigned int capability; +} CapabilityEntry; + +static void +cogl_pipeline_add_capability (CoglPipeline *pipeline, + GQuark domain, + unsigned int capability) +{ + CapabilityEntry entry = { + .domain = domain, + .capability = capability, + }; + + if (!pipeline->capabilities) + pipeline->capabilities = g_array_new (FALSE, FALSE, sizeof (entry)); + + g_array_append_val (pipeline->capabilities, entry); +} + +void +cogl_pipeline_add_capability_from_snippet (CoglPipeline *pipeline, + CoglSnippet *snippet) +{ + GQuark capability_domain; + unsigned int capability; + + if (cogl_snippet_get_capability (snippet, &capability_domain, &capability)) + cogl_pipeline_add_capability (pipeline, capability_domain, capability); +} + +gboolean +cogl_pipeline_has_capability (CoglPipeline *pipeline, + GQuark domain, + unsigned int capability) +{ + int i; + + if (!pipeline->capabilities) + return FALSE; + + for (i = 0; i < pipeline->capabilities->len; i++) + { + CapabilityEntry *entry = &g_array_index (pipeline->capabilities, + CapabilityEntry, + i); + + if (entry->domain == domain && + entry->capability == capability) + return TRUE; + } + + return FALSE; +} diff --git a/cogl/cogl/cogl-pipeline.h b/cogl/cogl/cogl-pipeline.h index 483f8e20a..15d9b34b2 100644 --- a/cogl/cogl/cogl-pipeline.h +++ b/cogl/cogl/cogl-pipeline.h @@ -155,4 +155,9 @@ COGL_EXPORT int cogl_pipeline_get_uniform_location (CoglPipeline *pipeline, const char *uniform_name); +COGL_EXPORT gboolean +cogl_pipeline_has_capability (CoglPipeline *pipeline, + GQuark domain, + unsigned int capability); + G_END_DECLS diff --git a/cogl/cogl/cogl-snippet-private.h b/cogl/cogl/cogl-snippet-private.h index ead730387..e7d5ed6b6 100644 --- a/cogl/cogl/cogl-snippet-private.h +++ b/cogl/cogl/cogl-snippet-private.h @@ -66,7 +66,15 @@ struct _CoglSnippet char *pre; char *replace; char *post; + + GQuark capability_domain; + unsigned int capability; }; void _cogl_snippet_make_immutable (CoglSnippet *snippet); + +gboolean +cogl_snippet_get_capability (CoglSnippet *snippet, + GQuark *domain, + unsigned int *capability); diff --git a/cogl/cogl/cogl-snippet.c b/cogl/cogl/cogl-snippet.c index 8e14d5dc5..de5697868 100644 --- a/cogl/cogl/cogl-snippet.c +++ b/cogl/cogl/cogl-snippet.c @@ -194,3 +194,31 @@ _cogl_snippet_make_immutable (CoglSnippet *snippet) { snippet->immutable = TRUE; } + +void +cogl_snippet_set_capability (CoglSnippet *snippet, + GQuark domain, + unsigned int capability) +{ + g_return_if_fail (!snippet->capability_domain); + + snippet->capability_domain = domain; + snippet->capability = capability; +} + +gboolean +cogl_snippet_get_capability (CoglSnippet *snippet, + GQuark *domain, + unsigned int *capability) +{ + if (snippet->capability_domain) + { + *domain = snippet->capability_domain; + *capability = snippet->capability; + return TRUE; + } + else + { + return FALSE; + } +} diff --git a/cogl/cogl/cogl-snippet.h b/cogl/cogl/cogl-snippet.h index 03b0f92e9..07d6c43df 100644 --- a/cogl/cogl/cogl-snippet.h +++ b/cogl/cogl/cogl-snippet.h @@ -622,4 +622,9 @@ cogl_snippet_set_post (CoglSnippet *snippet, COGL_EXPORT const char * cogl_snippet_get_post (CoglSnippet *snippet); +COGL_EXPORT void +cogl_snippet_set_capability (CoglSnippet *snippet, + GQuark domain, + unsigned int capability); + G_END_DECLS