summaryrefslogtreecommitdiff
path: root/cogl/cogl-pipeline-cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'cogl/cogl-pipeline-cache.c')
-rw-r--r--cogl/cogl-pipeline-cache.c241
1 files changed, 35 insertions, 206 deletions
diff --git a/cogl/cogl-pipeline-cache.c b/cogl/cogl-pipeline-cache.c
index fab3614f..df4c4338 100644
--- a/cogl/cogl-pipeline-cache.c
+++ b/cogl/cogl-pipeline-cache.c
@@ -3,7 +3,7 @@
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
- * Copyright (C) 2011 Intel Corporation.
+ * Copyright (C) 2011, 2013 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -32,133 +32,47 @@
#include "cogl-context-private.h"
#include "cogl-pipeline-private.h"
#include "cogl-pipeline-cache.h"
+#include "cogl-pipeline-hash-table.h"
struct _CoglPipelineCache
{
- GHashTable *fragment_hash;
- GHashTable *vertex_hash;
- GHashTable *combined_hash;
+ CoglPipelineHashTable fragment_hash;
+ CoglPipelineHashTable vertex_hash;
+ CoglPipelineHashTable combined_hash;
};
-static unsigned int
-pipeline_fragment_hash (const void *data)
-{
- unsigned int fragment_state;
- unsigned int layer_fragment_state;
-
- _COGL_GET_CONTEXT (ctx, 0);
-
- fragment_state =
- _cogl_pipeline_get_state_for_fragment_codegen (ctx);
- layer_fragment_state =
- _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx);
-
- return _cogl_pipeline_hash ((CoglPipeline *)data,
- fragment_state, layer_fragment_state,
- 0);
-}
-
-static CoglBool
-pipeline_fragment_equal (const void *a, const void *b)
+CoglPipelineCache *
+_cogl_pipeline_cache_new (void)
{
+ CoglPipelineCache *cache = g_new (CoglPipelineCache, 1);
+ unsigned long vertex_state;
+ unsigned long layer_vertex_state;
unsigned int fragment_state;
unsigned int layer_fragment_state;
_COGL_GET_CONTEXT (ctx, 0);
+ vertex_state =
+ COGL_PIPELINE_STATE_AFFECTS_VERTEX_CODEGEN;
+ layer_vertex_state =
+ COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN;
fragment_state =
_cogl_pipeline_get_state_for_fragment_codegen (ctx);
layer_fragment_state =
_cogl_pipeline_get_layer_state_for_fragment_codegen (ctx);
- return _cogl_pipeline_equal ((CoglPipeline *)a, (CoglPipeline *)b,
- fragment_state, layer_fragment_state,
- 0);
-}
-
-static unsigned int
-pipeline_vertex_hash (const void *data)
-{
- unsigned long vertex_state =
- COGL_PIPELINE_STATE_AFFECTS_VERTEX_CODEGEN;
- unsigned long layer_vertex_state =
- COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN;
-
- return _cogl_pipeline_hash ((CoglPipeline *)data,
- vertex_state, layer_vertex_state,
- 0);
-}
-
-static CoglBool
-pipeline_vertex_equal (const void *a, const void *b)
-{
- unsigned long vertex_state =
- COGL_PIPELINE_STATE_AFFECTS_VERTEX_CODEGEN;
- unsigned long layer_vertex_state =
- COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN;
-
- return _cogl_pipeline_equal ((CoglPipeline *)a, (CoglPipeline *)b,
- vertex_state, layer_vertex_state,
- 0);
-}
-
-static unsigned int
-pipeline_combined_hash (const void *data)
-{
- unsigned int combined_state;
- unsigned int layer_combined_state;
-
- _COGL_GET_CONTEXT (ctx, 0);
-
- combined_state =
- _cogl_pipeline_get_state_for_fragment_codegen (ctx) |
- COGL_PIPELINE_STATE_AFFECTS_VERTEX_CODEGEN;
- layer_combined_state =
- _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx) |
- COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN;
-
- return _cogl_pipeline_hash ((CoglPipeline *)data,
- combined_state, layer_combined_state,
- 0);
-}
-
-static CoglBool
-pipeline_combined_equal (const void *a, const void *b)
-{
- unsigned int combined_state;
- unsigned int layer_combined_state;
-
- _COGL_GET_CONTEXT (ctx, 0);
-
- combined_state =
- _cogl_pipeline_get_state_for_fragment_codegen (ctx) |
- COGL_PIPELINE_STATE_AFFECTS_VERTEX_CODEGEN;
- layer_combined_state =
- _cogl_pipeline_get_layer_state_for_fragment_codegen (ctx) |
- COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN;
-
- return _cogl_pipeline_equal ((CoglPipeline *)a, (CoglPipeline *)b,
- combined_state, layer_combined_state,
- 0);
-}
-
-CoglPipelineCache *
-_cogl_pipeline_cache_new (void)
-{
- CoglPipelineCache *cache = g_new (CoglPipelineCache, 1);
-
- cache->fragment_hash = g_hash_table_new_full (pipeline_fragment_hash,
- pipeline_fragment_equal,
- cogl_object_unref,
- cogl_object_unref);
- cache->vertex_hash = g_hash_table_new_full (pipeline_vertex_hash,
- pipeline_vertex_equal,
- cogl_object_unref,
- cogl_object_unref);
- cache->combined_hash = g_hash_table_new_full (pipeline_combined_hash,
- pipeline_combined_equal,
- cogl_object_unref,
- cogl_object_unref);
+ _cogl_pipeline_hash_table_init (&cache->vertex_hash,
+ vertex_state,
+ layer_vertex_state,
+ "vertex shaders");
+ _cogl_pipeline_hash_table_init (&cache->fragment_hash,
+ fragment_state,
+ layer_fragment_state,
+ "fragment shaders");
+ _cogl_pipeline_hash_table_init (&cache->combined_hash,
+ vertex_state | fragment_state,
+ layer_vertex_state | layer_fragment_state,
+ "programs");
return cache;
}
@@ -166,9 +80,9 @@ _cogl_pipeline_cache_new (void)
void
_cogl_pipeline_cache_free (CoglPipelineCache *cache)
{
- g_hash_table_destroy (cache->fragment_hash);
- g_hash_table_destroy (cache->vertex_hash);
- g_hash_table_destroy (cache->combined_hash);
+ _cogl_pipeline_hash_table_destroy (&cache->fragment_hash);
+ _cogl_pipeline_hash_table_destroy (&cache->vertex_hash);
+ _cogl_pipeline_hash_table_destroy (&cache->combined_hash);
g_free (cache);
}
@@ -176,107 +90,22 @@ CoglPipeline *
_cogl_pipeline_cache_get_fragment_template (CoglPipelineCache *cache,
CoglPipeline *key_pipeline)
{
- CoglPipeline *template =
- g_hash_table_lookup (cache->fragment_hash, key_pipeline);
-
- if (template == NULL)
- {
- /* XXX: I wish there was a way to insert into a GHashTable with
- * a pre-calculated hash value since there is a cost to
- * calculating the hash of a CoglPipeline and in this case we
- * know we have already called _cogl_pipeline_hash during the
- * lookup so we could pass the value through to here to avoid
- * hashing it again.
- */
-
- /* XXX: Any keys referenced by the hash table need to remain
- * valid all the while that there are corresponding values,
- * so for now we simply make a copy of the current authority
- * pipeline.
- *
- * FIXME: A problem with this is that our key into the cache may
- * hold references to some arbitrary user textures which will
- * now be kept alive indefinitly which is a shame. A better
- * solution will be to derive a special "key pipeline" from the
- * authority which derives from the base Cogl pipeline (to avoid
- * affecting the lifetime of any other pipelines) and only takes
- * a copy of the state that relates to the fragment shader and
- * references small dummy textures instead of potentially large
- * user textures. */
- template = cogl_pipeline_copy (key_pipeline);
-
- g_hash_table_insert (cache->fragment_hash,
- template,
- cogl_object_ref (template));
-
- if (G_UNLIKELY (g_hash_table_size (cache->fragment_hash) > 50))
- {
- static CoglBool seen = FALSE;
- if (!seen)
- g_warning ("Over 50 separate fragment shaders have been "
- "generated which is very unusual, so something "
- "is probably wrong!\n");
- seen = TRUE;
- }
- }
-
- return template;
+ return _cogl_pipeline_hash_table_get (&cache->fragment_hash,
+ key_pipeline);
}
CoglPipeline *
_cogl_pipeline_cache_get_vertex_template (CoglPipelineCache *cache,
CoglPipeline *key_pipeline)
{
- CoglPipeline *template =
- g_hash_table_lookup (cache->vertex_hash, key_pipeline);
-
- if (template == NULL)
- {
- template = cogl_pipeline_copy (key_pipeline);
-
- g_hash_table_insert (cache->vertex_hash,
- template,
- cogl_object_ref (template));
-
- if (G_UNLIKELY (g_hash_table_size (cache->vertex_hash) > 50))
- {
- static CoglBool seen = FALSE;
- if (!seen)
- g_warning ("Over 50 separate vertex shaders have been "
- "generated which is very unusual, so something "
- "is probably wrong!\n");
- seen = TRUE;
- }
- }
-
- return template;
+ return _cogl_pipeline_hash_table_get (&cache->vertex_hash,
+ key_pipeline);
}
CoglPipeline *
_cogl_pipeline_cache_get_combined_template (CoglPipelineCache *cache,
CoglPipeline *key_pipeline)
{
- CoglPipeline *template =
- g_hash_table_lookup (cache->combined_hash, key_pipeline);
-
- if (template == NULL)
- {
- template = cogl_pipeline_copy (key_pipeline);
-
- g_hash_table_insert (cache->combined_hash,
- template,
- cogl_object_ref (template));
-
- if (G_UNLIKELY (g_hash_table_size (cache->combined_hash) > 50))
- {
- static CoglBool seen = FALSE;
- if (!seen)
- g_warning ("Over 50 separate programs have been "
- "generated which is very unusual, so something "
- "is probably wrong!\n");
- seen = TRUE;
- }
- }
-
- return template;
+ return _cogl_pipeline_hash_table_get (&cache->combined_hash,
+ key_pipeline);
}