summaryrefslogtreecommitdiff
path: root/cogl/cogl-pipeline-layer.c
diff options
context:
space:
mode:
authorNeil Roberts <neil@linux.intel.com>2013-03-26 11:17:55 +0000
committerNeil Roberts <neil@linux.intel.com>2013-04-04 13:38:43 +0100
commit20657d62451c65c27ab441dc5140e2a4e2c75674 (patch)
tree4722199bf32a44f4eff108c4398bdc13278baf6b /cogl/cogl-pipeline-layer.c
parent4e03bd47bf2371533143f7a30720f2079da8b621 (diff)
downloadcogl-20657d62451c65c27ab441dc5140e2a4e2c75674.tar.gz
pipeline-cache: Use a special trimmed down pipeline for the key
When a pipeline is added to the cache, a normal copy would previously be made to use as the key in the hash table. This copy keeps a reference to the real pipeline which means all of the resources it contains are retained forever, even if they aren't necessary to generate the hash. This patch changes it to create a trimmed down copy that only has the state necessary to generate the hash. A new function called _cogl_pipeline_deep_copy is added which makes a new pipeline that is directly a child of the root pipeline. It then copies over the pertinent state from the original pipeline. The pipeline state is copied using the existing _cogl_pipeline_copy_differences function. There was no equivalent function for the layer state so I have added one. That way the pipeline key doesn't have the texture data state and it doesn't hold a reference to the original pipeline so it should be much cheaper to keep around. Reviewed-by: Robert Bragg <robert@linux.intel.com> (cherry picked from commit e27e01c1215e7e7c7c0183ded11dd769bb112c5c)
Diffstat (limited to 'cogl/cogl-pipeline-layer.c')
-rw-r--r--cogl/cogl-pipeline-layer.c103
1 files changed, 103 insertions, 0 deletions
diff --git a/cogl/cogl-pipeline-layer.c b/cogl/cogl-pipeline-layer.c
index d9590c8b..9bc26ef6 100644
--- a/cogl/cogl-pipeline-layer.c
+++ b/cogl/cogl-pipeline-layer.c
@@ -42,6 +42,8 @@
#include "cogl-context-private.h"
#include "cogl-texture-private.h"
+#include <string.h>
+
static void
_cogl_pipeline_layer_free (CoglPipelineLayer *layer);
@@ -146,6 +148,107 @@ _cogl_get_n_args_for_combine_func (CoglPipelineCombineFunc func)
return 0;
}
+void
+_cogl_pipeline_layer_copy_differences (CoglPipelineLayer *dest,
+ CoglPipelineLayer *src,
+ unsigned long differences)
+{
+ CoglPipelineLayerBigState *big_dest, *big_src;
+
+ if ((differences & COGL_PIPELINE_LAYER_STATE_NEEDS_BIG_STATE) &&
+ !dest->has_big_state)
+ {
+ dest->big_state = g_slice_new (CoglPipelineLayerBigState);
+ dest->has_big_state = TRUE;
+ }
+
+ big_dest = dest->big_state;
+ big_src = src->big_state;
+
+ dest->differences |= differences;
+
+ while (differences)
+ {
+ int index = _cogl_util_ffs (differences) - 1;
+
+ differences &= ~(1 << index);
+
+ /* This convoluted switch statement is just here so that we'll
+ * get a warning if a new state is added without handling it
+ * here */
+ switch (index)
+ {
+ case COGL_PIPELINE_LAYER_STATE_COUNT:
+ case COGL_PIPELINE_LAYER_STATE_UNIT_INDEX:
+ g_warn_if_reached ();
+ break;
+
+ case COGL_PIPELINE_LAYER_STATE_TEXTURE_TYPE_INDEX:
+ dest->texture_type = src->texture_type;
+ break;
+
+ case COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA_INDEX:
+ dest->texture = src->texture;
+ if (dest->texture)
+ cogl_object_ref (dest->texture);
+ break;
+
+ case COGL_PIPELINE_LAYER_STATE_SAMPLER_INDEX:
+ dest->sampler_cache_entry = src->sampler_cache_entry;
+ break;
+
+ case COGL_PIPELINE_LAYER_STATE_COMBINE_INDEX:
+ {
+ CoglPipelineCombineFunc func;
+ int n_args, i;
+
+ func = big_src->texture_combine_rgb_func;
+ big_dest->texture_combine_rgb_func = func;
+ n_args = _cogl_get_n_args_for_combine_func (func);
+ for (i = 0; i < n_args; i++)
+ {
+ big_dest->texture_combine_rgb_src[i] =
+ big_src->texture_combine_rgb_src[i];
+ big_dest->texture_combine_rgb_op[i] =
+ big_src->texture_combine_rgb_op[i];
+ }
+
+ func = big_src->texture_combine_alpha_func;
+ big_dest->texture_combine_alpha_func = func;
+ n_args = _cogl_get_n_args_for_combine_func (func);
+ for (i = 0; i < n_args; i++)
+ {
+ big_dest->texture_combine_alpha_src[i] =
+ big_src->texture_combine_alpha_src[i];
+ big_dest->texture_combine_alpha_op[i] =
+ big_src->texture_combine_alpha_op[i];
+ }
+ }
+ break;
+
+ case COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT_INDEX:
+ memcpy (big_dest->texture_combine_constant,
+ big_src->texture_combine_constant,
+ sizeof (big_dest->texture_combine_constant));
+ break;
+
+ case COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS_INDEX:
+ big_dest->point_sprite_coords = big_src->point_sprite_coords;
+ break;
+
+ case COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS_INDEX:
+ _cogl_pipeline_snippet_list_copy (&big_dest->vertex_snippets,
+ &big_src->vertex_snippets);
+ break;
+
+ case COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS_INDEX:
+ _cogl_pipeline_snippet_list_copy (&big_dest->fragment_snippets,
+ &big_src->fragment_snippets);
+ break;
+ }
+ }
+}
+
static void
_cogl_pipeline_layer_init_multi_property_sparse_state (
CoglPipelineLayer *layer,