diff options
Diffstat (limited to 'cogl/cogl-pipeline-cache.c')
-rw-r--r-- | cogl/cogl-pipeline-cache.c | 241 |
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); } |