diff --git a/srcpkgs/cogl/patches/cogl-1.14.0-21-ge26464f.patch b/srcpkgs/cogl/patches/cogl-1.14.0-21-ge26464f.patch new file mode 100644 index 0000000000..80e96c5dbd --- /dev/null +++ b/srcpkgs/cogl/patches/cogl-1.14.0-21-ge26464f.patch @@ -0,0 +1,1434 @@ +Only things missing here from upstream are translations and .gitignore changes + +diff --git a/cogl/Makefile.am b/cogl/Makefile.am +index 33214ab..80d3b09 100644 +--- a/cogl/Makefile.am ++++ b/cogl/Makefile.am +@@ -349,6 +349,8 @@ cogl_sources_c = \ + $(srcdir)/cogl-pipeline-snippet.c \ + $(srcdir)/cogl-pipeline-cache.h \ + $(srcdir)/cogl-pipeline-cache.c \ ++ $(srcdir)/cogl-pipeline-hash-table.h \ ++ $(srcdir)/cogl-pipeline-hash-table.c \ + $(srcdir)/cogl-material-compat.c \ + $(srcdir)/cogl-program.c \ + $(srcdir)/cogl-program-private.h \ +@@ -552,7 +554,7 @@ include $(top_srcdir)/build/autotools/Makefile.am.enums + + lib_LTLIBRARIES += libcogl.la + +-libcogl_la_LIBADD = -lm $(COGL_DEP_LIBS) $(COGL_EXTRA_LDFLAGS) ++libcogl_la_LIBADD = $(LIBM) $(COGL_DEP_LIBS) $(COGL_EXTRA_LDFLAGS) + if !USE_GLIB + libcogl_la_LIBADD += $(top_builddir)/deps/glib/libglib.la + libcogl_la_LIBADD += $(top_builddir)/deps/gmodule/libgmodule.la +diff --git a/cogl/cogl-bitmap-pixbuf.c b/cogl/cogl-bitmap-pixbuf.c +index a02b253..ad34234 100644 +--- a/cogl/cogl-bitmap-pixbuf.c ++++ b/cogl/cogl-bitmap-pixbuf.c +@@ -125,11 +125,24 @@ _cogl_bitmap_from_file (CoglContext *ctx, + /* allocate buffer big enough to hold pixel data */ + bmp = _cogl_bitmap_new_with_malloc_buffer (ctx, + width, height, +- COGL_PIXEL_FORMAT_ARGB_8888); ++ COGL_PIXEL_FORMAT_ARGB_8888, ++ error); ++ if (bmp == NULL) ++ { ++ CFRelease (image); ++ return NULL; ++ } + rowstride = cogl_bitmap_get_rowstride (bmp); + out_data = _cogl_bitmap_map (bmp, + COGL_BUFFER_ACCESS_WRITE, +- COGL_BUFFER_MAP_HINT_DISCARD); ++ COGL_BUFFER_MAP_HINT_DISCARD, ++ error); ++ if (out_data == NULL) ++ { ++ cogl_object_unref (bmp); ++ CFRelease (image); ++ return NULL; ++ } + + /* render to buffer */ + color_space = CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB); +diff --git a/cogl/cogl-matrix.h b/cogl/cogl-matrix.h +index 90f3ea9..a136ea0 100644 +--- a/cogl/cogl-matrix.h ++++ b/cogl/cogl-matrix.h +@@ -27,6 +27,8 @@ + #ifndef __COGL_MATRIX_H + #define __COGL_MATRIX_H + ++#include ++ + #ifdef COGL_HAS_GTYPE_SUPPORT + #include + #endif /* COGL_HAS_GTYPE_SUPPORT */ +diff --git a/cogl/cogl-pipeline-cache.c b/cogl/cogl-pipeline-cache.c +index fab3614..df4c433 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); + } +diff --git a/cogl/cogl-pipeline-hash-table.c b/cogl/cogl-pipeline-hash-table.c +new file mode 100644 +index 0000000..8921efc +--- /dev/null ++++ b/cogl/cogl-pipeline-hash-table.c +@@ -0,0 +1,153 @@ ++/* ++ * Cogl ++ * ++ * An object oriented GL/GLES Abstraction/Utility Layer ++ * ++ * Copyright (C) 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 ++ * 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 ++ * . ++ * ++ * ++ * Authors: ++ * Neil Roberts ++ * Robert Bragg ++ */ ++ ++#ifdef HAVE_CONFIG_H ++#include "config.h" ++#endif ++ ++#include "cogl-context-private.h" ++#include "cogl-pipeline-private.h" ++#include "cogl-pipeline-hash-table.h" ++ ++typedef struct ++{ ++ /* The template pipeline */ ++ CoglPipeline *pipeline; ++ ++ /* Calculating the hash is a little bit expensive for pipelines so ++ * we don't want to do it repeatedly for entries that are already in ++ * the hash table. Instead we cache the value here and calculate it ++ * outside of the GHashTable. */ ++ unsigned int hash_value; ++ ++ /* GHashTable annoyingly doesn't let us pass a user data pointer to ++ * the hash and equal functions so to work around it we have to ++ * store the pointer in every hash table entry. We will use this ++ * entry as both the key and the value */ ++ CoglPipelineHashTable *hash; ++} CoglPipelineHashTableEntry; ++ ++static void ++value_destroy_cb (void *value) ++{ ++ CoglPipelineHashTableEntry *entry = value; ++ ++ cogl_object_unref (entry->pipeline); ++ ++ g_slice_free (CoglPipelineHashTableEntry, entry); ++} ++ ++static unsigned int ++entry_hash (const void *data) ++{ ++ const CoglPipelineHashTableEntry *entry = data; ++ ++ return entry->hash_value; ++} ++ ++static CoglBool ++entry_equal (const void *a, ++ const void *b) ++{ ++ const CoglPipelineHashTableEntry *entry_a = a; ++ const CoglPipelineHashTableEntry *entry_b = b; ++ const CoglPipelineHashTable *hash = entry_a->hash; ++ ++ return _cogl_pipeline_equal (entry_a->pipeline, ++ entry_b->pipeline, ++ hash->main_state, ++ hash->layer_state, ++ 0); ++} ++ ++void ++_cogl_pipeline_hash_table_init (CoglPipelineHashTable *hash, ++ unsigned int main_state, ++ unsigned int layer_state, ++ const char *debug_string) ++{ ++ hash->n_unique_pipelines = 0; ++ hash->debug_string = debug_string; ++ hash->main_state = main_state; ++ hash->layer_state = layer_state; ++ hash->table = g_hash_table_new_full (entry_hash, ++ entry_equal, ++ NULL, /* key destroy */ ++ value_destroy_cb); ++} ++ ++void ++_cogl_pipeline_hash_table_destroy (CoglPipelineHashTable *hash) ++{ ++ g_hash_table_destroy (hash->table); ++} ++ ++CoglPipeline * ++_cogl_pipeline_hash_table_get (CoglPipelineHashTable *hash, ++ CoglPipeline *key_pipeline) ++{ ++ CoglPipelineHashTableEntry dummy_entry; ++ CoglPipelineHashTableEntry *entry; ++ unsigned int copy_state; ++ ++ dummy_entry.pipeline = key_pipeline; ++ dummy_entry.hash = hash; ++ dummy_entry.hash_value = _cogl_pipeline_hash (key_pipeline, ++ hash->main_state, ++ hash->layer_state, ++ 0); ++ entry = g_hash_table_lookup (hash->table, &dummy_entry); ++ ++ if (entry) ++ return entry->pipeline; ++ ++ if (hash->n_unique_pipelines == 50) ++ g_warning ("Over 50 separate %s have been generated which is very " ++ "unusual, so something is probably wrong!\n", ++ hash->debug_string); ++ ++ entry = g_slice_new (CoglPipelineHashTableEntry); ++ entry->hash = hash; ++ entry->hash_value = dummy_entry.hash_value; ++ ++ copy_state = hash->main_state; ++ if (hash->layer_state) ++ copy_state |= COGL_PIPELINE_STATE_LAYERS; ++ ++ /* Create a new pipeline that is a child of the root pipeline ++ * instead of a normal copy so that the template pipeline won't hold ++ * a reference to the original pipeline */ ++ entry->pipeline = _cogl_pipeline_deep_copy (key_pipeline, ++ copy_state, ++ hash->layer_state); ++ ++ g_hash_table_insert (hash->table, entry, entry); ++ ++ hash->n_unique_pipelines++; ++ ++ return entry->pipeline; ++} +diff --git a/cogl/cogl-pipeline-hash-table.h b/cogl/cogl-pipeline-hash-table.h +new file mode 100644 +index 0000000..1b0a0d9 +--- /dev/null ++++ b/cogl/cogl-pipeline-hash-table.h +@@ -0,0 +1,69 @@ ++/* ++ * Cogl ++ * ++ * An object oriented GL/GLES Abstraction/Utility Layer ++ * ++ * Copyright (C) 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 ++ * 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 . ++ * ++ * ++ */ ++ ++#ifndef __COGL_PIPELINE_HASH_H__ ++#define __COGL_PIPELINE_HASH_H__ ++ ++#include "cogl-pipeline.h" ++ ++typedef struct ++{ ++ /* Total number of pipelines that were ever added to the hash. This ++ * is not decremented when a pipeline is removed. It is only used to ++ * generate a warning if an unusually high number of pipelines are ++ * generated */ ++ int n_unique_pipelines; ++ ++ /* String that will be used to describe the usage of this hash table ++ * in the debug warning when too many pipelines are generated. This ++ * must be a static string because it won't be copied or freed */ ++ const char *debug_string; ++ ++ unsigned int main_state; ++ unsigned int layer_state; ++ ++ GHashTable *table; ++} CoglPipelineHashTable; ++ ++void ++_cogl_pipeline_hash_table_init (CoglPipelineHashTable *hash, ++ unsigned int main_state, ++ unsigned int layer_state, ++ const char *debug_string); ++ ++void ++_cogl_pipeline_hash_table_destroy (CoglPipelineHashTable *hash); ++ ++/* ++ * Gets a pipeline from the hash that has the same state as ++ * @key_pipeline according to the limited state bits passed to ++ * _cogl_pipeline_hash_table_init(). If there is no matching pipelines ++ * already then a copy of key_pipeline is stored in the hash so that ++ * it will be used next time the function is called with a similar ++ * pipeline. In that case the copy itself will be returned ++ */ ++CoglPipeline * ++_cogl_pipeline_hash_table_get (CoglPipelineHashTable *hash, ++ CoglPipeline *key_pipeline); ++ ++#endif /* __COGL_PIPELINE_HASH_H__ */ +diff --git a/cogl/cogl-pipeline-layer-private.h b/cogl/cogl-pipeline-layer-private.h +index 125b967..7577559 100644 +--- a/cogl/cogl-pipeline-layer-private.h ++++ b/cogl/cogl-pipeline-layer-private.h +@@ -358,6 +358,11 @@ _cogl_pipeline_layer_get_wrap_mode_t (CoglPipelineLayer *layer); + CoglPipelineWrapMode + _cogl_pipeline_layer_get_wrap_mode_p (CoglPipelineLayer *layer); + ++void ++_cogl_pipeline_layer_copy_differences (CoglPipelineLayer *dest, ++ CoglPipelineLayer *src, ++ unsigned long differences); ++ + unsigned long + _cogl_pipeline_layer_compare_differences (CoglPipelineLayer *layer0, + CoglPipelineLayer *layer1); +diff --git a/cogl/cogl-pipeline-layer.c b/cogl/cogl-pipeline-layer.c +index d9590c8..9bc26ef 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 ++ + 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, +diff --git a/cogl/cogl-pipeline-private.h b/cogl/cogl-pipeline-private.h +index 56700b5..acb5653 100644 +--- a/cogl/cogl-pipeline-private.h ++++ b/cogl/cogl-pipeline-private.h +@@ -845,6 +845,17 @@ _cogl_pipeline_hash (CoglPipeline *pipeline, + unsigned long layer_differences, + CoglPipelineEvalFlags flags); + ++/* Makes a copy of the given pipeline that is a child of the root ++ * pipeline rather than a child of the source pipeline. That way the ++ * new pipeline won't hold a reference to the source pipeline. The ++ * differences specified in @differences and @layer_differences are ++ * copied across and all other state is left with the default ++ * values. */ ++CoglPipeline * ++_cogl_pipeline_deep_copy (CoglPipeline *pipeline, ++ unsigned long differences, ++ unsigned long layer_differences); ++ + CoglPipeline * + _cogl_pipeline_journal_ref (CoglPipeline *pipeline); + +diff --git a/cogl/cogl-pipeline.c b/cogl/cogl-pipeline.c +index c029f45..a91ad25 100644 +--- a/cogl/cogl-pipeline.c ++++ b/cogl/cogl-pipeline.c +@@ -2771,6 +2771,97 @@ _cogl_pipeline_hash (CoglPipeline *pipeline, + + typedef struct + { ++ CoglContext *context; ++ CoglPipeline *src_pipeline; ++ CoglPipeline *dst_pipeline; ++ unsigned int layer_differences; ++} DeepCopyData; ++ ++static CoglBool ++deep_copy_layer_cb (CoglPipelineLayer *src_layer, ++ void *user_data) ++{ ++ DeepCopyData *data = user_data; ++ CoglPipelineLayer *dst_layer; ++ unsigned int differences = data->layer_differences; ++ ++ dst_layer = _cogl_pipeline_get_layer (data->dst_pipeline, src_layer->index); ++ ++ while (src_layer != data->context->default_layer_n && ++ src_layer != data->context->default_layer_0 && ++ differences) ++ { ++ unsigned long to_copy = differences & src_layer->differences; ++ ++ if (to_copy) ++ { ++ _cogl_pipeline_layer_copy_differences (dst_layer, src_layer, to_copy); ++ differences ^= to_copy; ++ } ++ ++ src_layer = COGL_PIPELINE_LAYER (COGL_NODE (src_layer)->parent); ++ } ++ ++ return TRUE; ++} ++ ++CoglPipeline * ++_cogl_pipeline_deep_copy (CoglPipeline *pipeline, ++ unsigned long differences, ++ unsigned long layer_differences) ++{ ++ CoglPipeline *new, *authority; ++ CoglBool copy_layer_state; ++ ++ _COGL_GET_CONTEXT (ctx, NULL); ++ ++ if ((differences & COGL_PIPELINE_STATE_LAYERS)) ++ { ++ copy_layer_state = TRUE; ++ differences &= ~COGL_PIPELINE_STATE_LAYERS; ++ } ++ else ++ copy_layer_state = FALSE; ++ ++ new = cogl_pipeline_new (ctx); ++ ++ for (authority = pipeline; ++ authority != ctx->default_pipeline && differences; ++ authority = COGL_PIPELINE (COGL_NODE (authority)->parent)) ++ { ++ unsigned long to_copy = differences & authority->differences; ++ ++ if (to_copy) ++ { ++ _cogl_pipeline_copy_differences (new, authority, to_copy); ++ differences ^= to_copy; ++ } ++ } ++ ++ if (copy_layer_state) ++ { ++ DeepCopyData data; ++ ++ /* The unit index doesn't need to be copied because it should ++ * end up with the same values anyway because the new pipeline ++ * will have the same indices as the source pipeline */ ++ layer_differences &= ~COGL_PIPELINE_LAYER_STATE_UNIT; ++ ++ data.context = ctx; ++ data.src_pipeline = pipeline; ++ data.dst_pipeline = new; ++ data.layer_differences = layer_differences; ++ ++ _cogl_pipeline_foreach_layer_internal (pipeline, ++ deep_copy_layer_cb, ++ &data); ++ } ++ ++ return new; ++} ++ ++typedef struct ++{ + int i; + CoglPipelineLayer **layers; + } AddLayersToArrayState; +diff --git a/cogl/cogl-xlib-renderer.c b/cogl/cogl-xlib-renderer.c +index 18c0fe6..eb1f51a 100644 +--- a/cogl/cogl-xlib-renderer.c ++++ b/cogl/cogl-xlib-renderer.c +@@ -238,7 +238,7 @@ update_outputs (CoglRenderer *renderer, + + _cogl_xlib_renderer_trap_errors (renderer, &state); + +- for (i = 0; i < resources->ncrtc && !error; i++) ++ for (i = 0; resources && i < resources->ncrtc && !error; i++) + { + XRRCrtcInfo *crtc_info = NULL; + XRROutputInfo *output_info = NULL; +diff --git a/cogl/cogl-xlib.h b/cogl/cogl-xlib.h +index 7a6bc7e..5dab8ae 100644 +--- a/cogl/cogl-xlib.h ++++ b/cogl/cogl-xlib.h +@@ -79,6 +79,8 @@ cogl_xlib_set_display (Display *display); + CoglFilterReturn + cogl_xlib_handle_event (XEvent *xevent); + ++COGL_END_DECLS ++ + #undef __COGL_XLIB_H_INSIDE__ + + #endif /* __COGL_XLIB_H__ */ +diff --git a/configure.ac b/configure.ac +index 43bf407..4ba85b8 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -25,7 +25,7 @@ m4_define([cogl_version], + dnl Since the core Cogl library has to also maintain support for the + dnl Cogl 1.x API for Clutter then we track the 1.x version separately. + m4_define([cogl_1_minor_version], [14]) +-m4_define([cogl_1_micro_version], [0]) ++m4_define([cogl_1_micro_version], [1]) + m4_define([cogl_1_version], [1.cogl_1_minor_version.cogl_1_micro_version]) + + dnl ================================================================ +@@ -70,7 +70,7 @@ dnl ================================================================ + # libtool version info we don't automatically derive this from the + # pretty version number because we want to test the results of + # updating the version number in advance of a release. +-m4_define([cogl_release_status], [release]) ++m4_define([cogl_release_status], [git]) + + AC_INIT(cogl, [cogl_1_version]) + AC_CONFIG_SRCDIR(cogl/cogl.h) +@@ -178,6 +178,12 @@ dnl internal glib configure (as-glibconfig.m4) + m4_ifdef([LT_OUTPUT], [LT_OUTPUT]) + + dnl ================================================================ ++dnl Find an appropriate libm, for sin() etc. ++dnl ================================================================ ++LT_LIB_M ++AC_SUBST(LIBM) ++ ++dnl ================================================================ + dnl See what platform we are building for + dnl ================================================================ + AC_CANONICAL_HOST +@@ -474,6 +480,7 @@ AS_IF( + EXPERIMENTAL_OPTIONS="$EXPERIMENTAL_OPTIONS Quartz Core Graphics," + AC_DEFINE([USE_QUARTZ], 1, + [Use Core Graphics (Quartz) for loading image data]) ++ COGL_EXTRA_LDFLAGS="$COGL_EXTRA_LDFLAGS -framework ApplicationServices" + COGL_IMAGE_BACKEND="quartz" + ], + [ +@@ -1173,6 +1180,12 @@ AC_CHECK_FUNCS([ffs]) + dnl 'memmem' is a GNU extension but we have a simple fallback + AC_CHECK_FUNCS([memmem]) + ++dnl This is used in the cogl-gles2-gears example but it is a GNU extension ++save_libs="$LIBS" ++LIBS="$LIBS $LIBM" ++AC_CHECK_FUNCS([sincos]) ++LIBS="$save_libs" ++ + dnl ================================================================ + dnl Platform values + dnl ================================================================ +diff --git a/examples/Makefile.am b/examples/Makefile.am +index 86801c6..ae3e5f7 100644 +--- a/examples/Makefile.am ++++ b/examples/Makefile.am +@@ -20,7 +20,8 @@ endif + + common_ldadd = \ + $(COGL_DEP_LIBS) \ +- $(top_builddir)/cogl/libcogl.la ++ $(top_builddir)/cogl/libcogl.la \ ++ $(LIBM) + + if !USE_GLIB + common_ldadd += $(top_builddir)/deps/glib/libglib.la +diff --git a/examples/android/hello/jni/main.c b/examples/android/hello/jni/main.c +index 2c5bd9b..c9a8401 100644 +--- a/examples/android/hello/jni/main.c ++++ b/examples/android/hello/jni/main.c +@@ -42,7 +42,7 @@ static int test_init (TestData* data) + CoglOnscreen *onscreen; + CoglError *error = NULL; + CoglVertexP2C4 triangle_vertices[] = { +- {0, 0.7, 0xff, 0x00, 0x00, 0x80}, ++ {0, 0.7, 0xff, 0x00, 0x00, 0xff}, + {-0.7, -0.7, 0x00, 0xff, 0x00, 0xff}, + {0.7, -0.7, 0x00, 0x00, 0xff, 0xff} + }; +diff --git a/examples/cogl-gles2-context.c b/examples/cogl-gles2-context.c +index 1cf375f..de66c21 100644 +--- a/examples/cogl-gles2-context.c ++++ b/examples/cogl-gles2-context.c +@@ -70,7 +70,7 @@ main (int argc, char **argv) + CoglOnscreen *onscreen; + CoglError *error = NULL; + CoglVertexP2C4 triangle_vertices[] = { +- {0, 0.7, 0xff, 0x00, 0x00, 0x80}, ++ {0, 0.7, 0xff, 0x00, 0x00, 0xff}, + {-0.7, -0.7, 0x00, 0xff, 0x00, 0xff}, + {0.7, -0.7, 0x00, 0x00, 0xff, 0xff} + }; +diff --git a/examples/cogl-gles2-gears.c b/examples/cogl-gles2-gears.c +index d7dd271..c7185b6 100644 +--- a/examples/cogl-gles2-gears.c ++++ b/examples/cogl-gles2-gears.c +@@ -35,6 +35,10 @@ + * Jul 13, 2010 + */ + ++#ifdef HAVE_CONFIG_H ++#include "config.h" ++#endif ++ + #define GL_GLEXT_PROTOTYPES + + #include +@@ -110,6 +114,15 @@ static GLfloat ProjectionMatrix[16]; + /** The direction of the directional light for the scene */ + static const GLfloat LightSourcePosition[4] = { 5.0, 5.0, 10.0, 1.0}; + ++#ifndef HAVE_SINCOS ++static void ++sincos (double x, double *sinx, double *cosx) ++{ ++ *sinx = sin (x); ++ *cosx = cos (x); ++} ++#endif /* HAVE_SINCOS */ ++ + /** + * Fills a gear vertex. + * +diff --git a/examples/cogl-hello.c b/examples/cogl-hello.c +index 5bda9bf..3ba1e31 100644 +--- a/examples/cogl-hello.c ++++ b/examples/cogl-hello.c +@@ -39,7 +39,7 @@ main (int argc, char **argv) + CoglOnscreen *onscreen; + CoglError *error = NULL; + CoglVertexP2C4 triangle_vertices[] = { +- {0, 0.7, 0xff, 0x00, 0x00, 0x80}, ++ {0, 0.7, 0xff, 0x00, 0x00, 0xff}, + {-0.7, -0.7, 0x00, 0xff, 0x00, 0xff}, + {0.7, -0.7, 0x00, 0x00, 0xff, 0xff} + }; +diff --git a/examples/cogl-msaa.c b/examples/cogl-msaa.c +index 73f9c4e..4a388bc 100644 +--- a/examples/cogl-msaa.c ++++ b/examples/cogl-msaa.c +@@ -12,7 +12,7 @@ main (int argc, char **argv) + CoglFramebuffer *fb; + CoglError *error = NULL; + CoglVertexP2C4 triangle_vertices[] = { +- {0, 0.7, 0xff, 0x00, 0x00, 0x80}, ++ {0, 0.7, 0xff, 0x00, 0x00, 0xff}, + {-0.7, -0.7, 0x00, 0xff, 0x00, 0xff}, + {0.7, -0.7, 0x00, 0x00, 0xff, 0xff} + }; +diff --git a/examples/cogl-sdl-hello.c b/examples/cogl-sdl-hello.c +index 961137a..acb9125 100644 +--- a/examples/cogl-sdl-hello.c ++++ b/examples/cogl-sdl-hello.c +@@ -80,7 +80,7 @@ main (int argc, char **argv) + CoglOnscreen *onscreen; + CoglError *error = NULL; + CoglVertexP2C4 triangle_vertices[] = { +- {0, 0.7, 0xff, 0x00, 0x00, 0x80}, ++ {0, 0.7, 0xff, 0x00, 0x00, 0xff}, + {-0.7, -0.7, 0x00, 0xff, 0x00, 0xff}, + {0.7, -0.7, 0x00, 0x00, 0xff, 0xff} + }; +diff --git a/examples/cogl-sdl2-hello.c b/examples/cogl-sdl2-hello.c +index 405cb92..12e6ced 100644 +--- a/examples/cogl-sdl2-hello.c ++++ b/examples/cogl-sdl2-hello.c +@@ -89,7 +89,7 @@ main (int argc, char **argv) + CoglOnscreen *onscreen; + CoglError *error = NULL; + CoglVertexP2C4 triangle_vertices[] = { +- {0, 0.7, 0xff, 0x00, 0x00, 0x80}, ++ {0, 0.7, 0xff, 0x00, 0x00, 0xff}, + {-0.7, -0.7, 0x00, 0xff, 0x00, 0xff}, + {0.7, -0.7, 0x00, 0x00, 0xff, 0xff} + }; +diff --git a/examples/cogl-x11-foreign.c b/examples/cogl-x11-foreign.c +index ca9e3ed..a60397c 100644 +--- a/examples/cogl-x11-foreign.c ++++ b/examples/cogl-x11-foreign.c +@@ -61,7 +61,7 @@ main (int argc, char **argv) + unsigned long mask; + Window xwin; + CoglVertexP2C4 triangle_vertices[] = { +- {0, 0.7, 0xff, 0x00, 0x00, 0x80}, ++ {0, 0.7, 0xff, 0x00, 0x00, 0xff}, + {-0.7, -0.7, 0x00, 0xff, 0x00, 0xff}, + {0.7, -0.7, 0x00, 0x00, 0xff, 0xff} + }; +diff --git a/examples/cogland.c b/examples/cogland.c +index c18850a..7a02719 100644 +--- a/examples/cogland.c ++++ b/examples/cogland.c +@@ -93,7 +93,6 @@ struct _CoglandCompositor + struct wl_display *wayland_display; + struct wl_event_loop *wayland_loop; + +- CoglDisplay *cogl_display; + CoglContext *cogl_context; + + int virtual_width; +@@ -336,15 +335,16 @@ cogland_queue_redraw (CoglandCompositor *compositor) + } + + static void +-shm_buffer_damaged (CoglandSurface *surface, +- int32_t x, +- int32_t y, +- int32_t width, +- int32_t height) ++surface_damaged (CoglandSurface *surface, ++ int32_t x, ++ int32_t y, ++ int32_t width, ++ int32_t height) + { + struct wl_buffer *wayland_buffer = surface->buffer; + +- if (surface->texture) ++ if (surface->texture && ++ wl_buffer_is_shm (surface->buffer)) + { + CoglPixelFormat format; + int stride = wl_shm_buffer_get_stride (wayland_buffer); +@@ -381,6 +381,8 @@ shm_buffer_damaged (CoglandSurface *surface, + stride, + data); + } ++ ++ cogland_queue_redraw (surface->compositor); + } + + static void +@@ -546,16 +548,18 @@ cogland_surface_commit (struct wl_client *client, + + wl_signal_add (&surface->buffer->resource.destroy_signal, + &surface->buffer_destroy_listener); +- wl_list_remove (&surface->pending.buffer_destroy_listener.link); + } + } +- surface->pending.buffer = NULL; ++ if (surface->pending.buffer) ++ { ++ wl_list_remove (&surface->pending.buffer_destroy_listener.link); ++ surface->pending.buffer = NULL; ++ } + surface->pending.sx = 0; + surface->pending.sy = 0; + + /* wl_surface.damage */ + if (surface->buffer && +- wl_buffer_is_shm (surface->buffer) && + surface->texture && + !region_is_empty (&surface->pending.damage)) + { +@@ -571,11 +575,11 @@ cogland_surface_commit (struct wl_client *client, + if (region->y1 < 0) + region->y1 = 0; + +- shm_buffer_damaged (surface, +- region->x1, +- region->y1, +- region->x2 - region->x1, +- region->y2 - region->y1); ++ surface_damaged (surface, ++ region->x1, ++ region->y1, ++ region->x2 - region->x1, ++ region->y2 - region->y1); + } + region_init (&surface->pending.damage); + +@@ -583,8 +587,6 @@ cogland_surface_commit (struct wl_client *client, + wl_list_insert_list (&compositor->frame_callbacks, + &surface->pending.frame_callback_list); + wl_list_init (&surface->pending.frame_callback_list); +- +- cogland_queue_redraw (compositor); + } + + static void +@@ -614,6 +616,9 @@ cogland_surface_free (CoglandSurface *surface) + compositor->surfaces = g_list_remove (compositor->surfaces, surface); + cogland_surface_detach_buffer_and_notify (surface); + ++ if (surface->pending.buffer) ++ wl_list_remove (&surface->pending.buffer_destroy_listener.link); ++ + wl_list_for_each_safe (cb, next, + &surface->pending.frame_callback_list, link) + wl_resource_destroy (&cb->resource); +@@ -970,7 +975,7 @@ get_shell_surface (struct wl_client *client, + struct wl_resource *surface_resource) + { + CoglandSurface *surface = surface_resource->data; +- CoglandShellSurface *shell_surface = g_new0 (CoglandShellSurface, 1); ++ CoglandShellSurface *shell_surface; + + if (surface->has_shell_surface) + { +@@ -980,6 +985,7 @@ get_shell_surface (struct wl_client *client, + return; + } + ++ shell_surface = g_new0 (CoglandShellSurface, 1); + shell_surface->resource.destroy = destroy_shell_surface; + shell_surface->resource.object.id = id; + shell_surface->resource.object.interface = &wl_shell_surface_interface; +@@ -1012,6 +1018,36 @@ bind_shell (struct wl_client *client, + &cogland_shell_interface, id, data); + } + ++static CoglContext * ++create_cogl_context (CoglandCompositor *compositor, ++ CoglBool use_egl_constraint, ++ CoglError **error) ++{ ++ CoglRenderer *renderer = renderer = cogl_renderer_new (); ++ CoglDisplay *display; ++ CoglContext *context; ++ ++ if (use_egl_constraint) ++ cogl_renderer_add_constraint (renderer, COGL_RENDERER_CONSTRAINT_USES_EGL); ++ ++ if (!cogl_renderer_connect (renderer, error)) ++ { ++ cogl_object_unref (renderer); ++ return NULL; ++ } ++ ++ display = cogl_display_new (renderer, NULL); ++ cogl_wayland_display_set_compositor_display (display, ++ compositor->wayland_display); ++ ++ context = cogl_context_new (display, error); ++ ++ cogl_object_unref (renderer); ++ cogl_object_unref (display); ++ ++ return context; ++} ++ + int + main (int argc, char **argv) + { +@@ -1020,7 +1056,7 @@ main (int argc, char **argv) + CoglError *error = NULL; + GError *gerror = NULL; + CoglVertexP2C4 triangle_vertices[] = { +- {0, 0.7, 0xff, 0x00, 0x00, 0x80}, ++ {0, 0.7, 0xff, 0x00, 0x00, 0xff}, + {-0.7, -0.7, 0x00, 0xff, 0x00, 0xff}, + {0.7, -0.7, 0x00, 0x00, 0xff, 0xff} + }; +@@ -1055,13 +1091,30 @@ main (int argc, char **argv) + wayland_event_source_new (compositor.wayland_display); + g_source_attach (compositor.wayland_event_source, NULL); + +- compositor.cogl_display = cogl_display_new (NULL, NULL); +- cogl_wayland_display_set_compositor_display (compositor.cogl_display, +- compositor.wayland_display); +- +- compositor.cogl_context = cogl_context_new (compositor.cogl_display, &error); +- if (!compositor.cogl_context) +- g_error ("Failed to create a Cogl context: %s\n", error->message); ++ /* We want Cogl to use an EGL renderer because otherwise it won't ++ * set up the wl_drm object and only SHM buffers will work. */ ++ compositor.cogl_context = ++ create_cogl_context (&compositor, ++ TRUE /* use EGL constraint */, ++ &error); ++ if (compositor.cogl_context == NULL) ++ { ++ /* If we couldn't get an EGL context then try any type of ++ * context */ ++ cogl_error_free (error); ++ error = NULL; ++ ++ compositor.cogl_context = ++ create_cogl_context (&compositor, ++ FALSE, /* don't set EGL constraint */ ++ &error); ++ ++ if (compositor.cogl_context) ++ g_warning ("Failed to create context with EGL constraint, " ++ "falling back"); ++ else ++ g_error ("Failed to create a Cogl context: %s\n", error->message); ++ } + + compositor.virtual_width = 800; + compositor.virtual_height = 600; +diff --git a/tests/conform/Makefile.am b/tests/conform/Makefile.am +index 69a460d..9782755 100644 +--- a/tests/conform/Makefile.am ++++ b/tests/conform/Makefile.am +@@ -65,6 +65,7 @@ test_sources = \ + test-framebuffer-get-bits.c \ + test-primitive-and-journal.c \ + test-copy-replace-texture.c \ ++ test-pipeline-cache-unrefs-texture.c \ + $(NULL) + + test_conformance_SOURCES = $(common_sources) $(test_sources) +@@ -131,7 +132,10 @@ AM_CPPFLAGS += \ + -DCOGL_COMPILATION + + test_conformance_CFLAGS = -g3 -O0 $(COGL_DEP_CFLAGS) $(COGL_EXTRA_CFLAGS) +-test_conformance_LDADD = $(COGL_DEP_LIBS) $(top_builddir)/cogl/libcogl.la ++test_conformance_LDADD = \ ++ $(COGL_DEP_LIBS) \ ++ $(top_builddir)/cogl/libcogl.la \ ++ $(LIBM) + if !USE_GLIB + test_conformance_LDADD += $(top_builddir)/deps/glib/libglib.la + endif +diff --git a/tests/conform/test-conform-main.c b/tests/conform/test-conform-main.c +index 0b55db6..1d1447e 100644 +--- a/tests/conform/test-conform-main.c ++++ b/tests/conform/test-conform-main.c +@@ -120,6 +120,8 @@ main (int argc, char **argv) + + ADD_TEST (test_copy_replace_texture, 0, 0); + ++ ADD_TEST (test_pipeline_cache_unrefs_texture, 0, 0); ++ + UNPORTED_TEST (test_viewport); + + ADD_TEST (test_gles2_context, TEST_REQUIREMENT_GLES2_CONTEXT, 0); +diff --git a/tests/conform/test-pipeline-cache-unrefs-texture.c b/tests/conform/test-pipeline-cache-unrefs-texture.c +new file mode 100644 +index 0000000..ccd02e7 +--- /dev/null ++++ b/tests/conform/test-pipeline-cache-unrefs-texture.c +@@ -0,0 +1,92 @@ ++#include ++ ++#include "test-utils.h" ++ ++/* Keep track of the number of textures that we've created and are ++ * still alive */ ++static int destroyed_texture_count = 0; ++ ++#define N_TEXTURES 3 ++ ++static void ++free_texture_cb (void *user_data) ++{ ++ destroyed_texture_count++; ++} ++ ++static CoglTexture * ++create_texture (void) ++{ ++ static const guint8 data[] = ++ { 0xff, 0xff, 0xff, 0xff }; ++ static CoglUserDataKey texture_data_key; ++ CoglTexture2D *tex_2d; ++ ++ tex_2d = cogl_texture_2d_new_from_data (test_ctx, ++ 1, 1, /* width / height */ ++ COGL_PIXEL_FORMAT_RGBA_8888_PRE, ++ COGL_PIXEL_FORMAT_ANY, ++ 4, /* rowstride */ ++ data, ++ NULL); ++ ++ /* Set some user data on the texture so we can track when it has ++ * been destroyed */ ++ cogl_object_set_user_data (COGL_OBJECT (tex_2d), ++ &texture_data_key, ++ GINT_TO_POINTER (1), ++ free_texture_cb); ++ ++ return COGL_TEXTURE (tex_2d); ++} ++ ++void ++test_pipeline_cache_unrefs_texture (void) ++{ ++ CoglPipeline *pipeline = cogl_pipeline_new (test_ctx); ++ CoglPipeline *simple_pipeline; ++ int i; ++ ++ /* Create a pipeline with three texture layers. That way we can be ++ * pretty sure the pipeline will cause a unique shader to be ++ * generated in the cache */ ++ for (i = 0; i < N_TEXTURES; i++) ++ { ++ CoglTexture *tex = create_texture (); ++ cogl_pipeline_set_layer_texture (pipeline, i, tex); ++ cogl_object_unref (tex); ++ } ++ ++ /* Draw something with the pipeline to ensure it gets into the ++ * pipeline cache */ ++ cogl_framebuffer_draw_rectangle (test_fb, ++ pipeline, ++ 0, 0, 10, 10); ++ cogl_framebuffer_finish (test_fb); ++ ++ /* Draw something else so that it is no longer the current flushed ++ * pipeline, and the units have a different texture bound */ ++ simple_pipeline = cogl_pipeline_new (test_ctx); ++ for (i = 0; i < N_TEXTURES; i++) ++ { ++ CoglColor combine_constant; ++ cogl_color_init_from_4ub (&combine_constant, i, 0, 0, 255); ++ cogl_pipeline_set_layer_combine_constant (simple_pipeline, ++ i, ++ &combine_constant); ++ } ++ cogl_framebuffer_draw_rectangle (test_fb, simple_pipeline, 0, 0, 10, 10); ++ cogl_framebuffer_finish (test_fb); ++ cogl_object_unref (simple_pipeline); ++ ++ g_assert_cmpint (destroyed_texture_count, ==, 0); ++ ++ /* Destroy the pipeline. This should immediately cause the textures ++ * to be freed */ ++ cogl_object_unref (pipeline); ++ ++ g_assert_cmpint (destroyed_texture_count, ==, N_TEXTURES); ++ ++ if (cogl_test_verbose ()) ++ g_print ("OK\n"); ++} +diff --git a/tests/micro-perf/Makefile.am b/tests/micro-perf/Makefile.am +index c221dd6..5c5f69d 100644 +--- a/tests/micro-perf/Makefile.am ++++ b/tests/micro-perf/Makefile.am +@@ -19,5 +19,10 @@ endif + + AM_CFLAGS = $(COGL_DEP_CFLAGS) $(COGL_EXTRA_CFLAGS) + ++common_ldadd = \ ++ $(COGL_DEP_LIBS) \ ++ $(top_builddir)/cogl/libcogl.la \ ++ $(LIBM) ++ + test_journal_SOURCES = test-journal.c +-test_journal_LDADD = $(COGL_DEP_LIBS) $(top_builddir)/cogl/libcogl.la ++test_journal_LDADD = $(common_ldadd) diff --git a/srcpkgs/cogl/patches/cogl-1.14.0-21-ge26464f.patch.args b/srcpkgs/cogl/patches/cogl-1.14.0-21-ge26464f.patch.args new file mode 100644 index 0000000000..2eba1cb3c5 --- /dev/null +++ b/srcpkgs/cogl/patches/cogl-1.14.0-21-ge26464f.patch.args @@ -0,0 +1 @@ +-Np1 diff --git a/srcpkgs/cogl/template b/srcpkgs/cogl/template index 9e0bf6addb..9cf63ea9c3 100644 --- a/srcpkgs/cogl/template +++ b/srcpkgs/cogl/template @@ -1,10 +1,10 @@ # Template file for 'cogl' pkgname=cogl version=1.14.0 -revision=2 +revision=3 build_style=gnu-configure configure_args="--enable-introspection" -hostmakedepends="pkg-config intltool gobject-introspection" +hostmakedepends="pkg-config intltool automake libtool gettext-devel gobject-introspection" makedepends="libXcomposite-devel libXrandr-devel libXdamage-devel pango-devel gdk-pixbuf-devel" short_desc="Library for using 3D graphics hardware for rendering" maintainer="Juan RP " @@ -13,13 +13,18 @@ license="LGPL-2.1" distfiles="${GNOME_SITE}/cogl/${version%.*}/cogl-${version}.tar.xz" checksum=276e8c9f5ff0fcd57c1eaf74cc245f41ad469a95a18ac831fac2d5960baa5ae8 +pre_configure() { + autoreconf -fi +} + cogl-devel_package() { depends="libdrm-devel libXcomposite-devel libXdamage-devel libXrandr-devel gdk-pixbuf-devel glib-devel cogl>=${version}" - short_desc="${short_desc} -- development files" + short_desc+=" - development files" pkg_install() { vmove usr/include vmove usr/lib/pkgconfig + vmove "usr/lib/*.so" vmove usr/share/gir-1.0 } }