mutter/cogl/cogl-pipeline-cache.c
Robert Bragg 54735dec84 Switch use of primitive glib types to c99 equivalents
The coding style has for a long time said to avoid using redundant glib
data types such as gint or gchar etc because we feel that they make the
code look unnecessarily foreign to developers coming from outside of the
Gnome developer community.

Note: When we tried to find the historical rationale for the types we
just found that they were apparently only added for consistent syntax
highlighting which didn't seem that compelling.

Up until now we have been continuing to use some of the platform
specific type such as gint{8,16,32,64} and gsize but this patch switches
us over to using the standard c99 equivalents instead so we can further
ensure that our code looks familiar to the widest range of C developers
who might potentially contribute to Cogl.

So instead of using the gint{8,16,32,64} and guint{8,16,32,64} types this
switches all Cogl code to instead use the int{8,16,32,64}_t and
uint{8,16,32,64}_t c99 types instead.

Instead of gsize we now use size_t

For now we are not going to use the c99 _Bool type and instead we have
introduced a new CoglBool type to use instead of gboolean.

Reviewed-by: Neil Roberts <neil@linux.intel.com>

(cherry picked from commit 5967dad2400d32ca6319cef6cb572e81bf2c15f0)
2012-08-06 14:27:39 +01:00

283 lines
8.9 KiB
C

/*
* Cogl
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
* Copyright (C) 2011 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*
*
* Authors:
* Neil Roberts <neil@linux.intel.com>
* Robert Bragg <robert@linux.intel.com>
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "cogl-context-private.h"
#include "cogl-pipeline-private.h"
#include "cogl-pipeline-cache.h"
struct _CoglPipelineCache
{
GHashTable *fragment_hash;
GHashTable *vertex_hash;
GHashTable *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)
{
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_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);
return cache;
}
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);
g_free (cache);
}
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;
}
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;
}
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;
}