diff options
author | root <root@rshg054.dnsready.net> | 2013-09-17 05:09:31 -0700 |
---|---|---|
committer | root <root@rshg054.dnsready.net> | 2013-09-17 05:09:31 -0700 |
commit | 7080cab465360c1e2571433323481aed6741ecbe (patch) | |
tree | ac430543eac4e1d1fa7f3512afdad29b5220863b /extra | |
parent | a1ec78e8d16098adb2e9e1cf4e364625e74c3bc4 (diff) |
Tue Sep 17 05:07:41 PDT 2013
Diffstat (limited to 'extra')
-rw-r--r-- | extra/cogl/PKGBUILD | 18 | ||||
-rw-r--r-- | extra/cogl/git-fixes.patch | 1948 |
2 files changed, 1962 insertions, 4 deletions
diff --git a/extra/cogl/PKGBUILD b/extra/cogl/PKGBUILD index 9b34a0460..72aa066c1 100644 --- a/extra/cogl/PKGBUILD +++ b/extra/cogl/PKGBUILD @@ -1,9 +1,9 @@ -# $Id: PKGBUILD 190118 2013-07-15 21:53:44Z tomegun $ +# $Id: PKGBUILD 194508 2013-09-17 02:50:40Z heftig $ # Maintainer: Ionut Biru <ibiru@archlinux.org> pkgname=cogl pkgver=1.14.0 -pkgrel=4 +pkgrel=5 pkgdesc="An object oriented GL/GLES Abstraction/Utility Layer" arch=('i686' 'x86_64') url="http://www.clutter-project.org/" @@ -11,11 +11,21 @@ license=('GPL2') depends=('libdrm' 'libxext' 'libxdamage' 'libxcomposite' 'gdk-pixbuf2' 'pango') makedepends=('mesa' 'gobject-introspection') options=(!libtool !emptydirs) -source=(http://download.gnome.org/sources/$pkgname/${pkgver%.*}/$pkgname-$pkgver.tar.xz) -sha256sums=('276e8c9f5ff0fcd57c1eaf74cc245f41ad469a95a18ac831fac2d5960baa5ae8') +source=(http://download.gnome.org/sources/$pkgname/${pkgver%.*}/$pkgname-$pkgver.tar.xz + git-fixes.patch) +sha256sums=('276e8c9f5ff0fcd57c1eaf74cc245f41ad469a95a18ac831fac2d5960baa5ae8' + '5f9279122cabf5cce23c1e19cedd9e67231f63a4d35329924b256fc1adc1aab2') + +prepare() { + cd "$pkgname-$pkgver" + # Update to ba5e5410babf705f53b591579c104181dd752bec + # Removed version parts from configure.ac and .gitignore parts, removed conflicting it.po and eu.po commits + patch -Np1 -i ../git-fixes.patch +} build() { cd "$pkgname-$pkgver" + autoreconf -fi ./configure --prefix=/usr \ --enable-wayland-egl-platform --enable-gles{1,2} diff --git a/extra/cogl/git-fixes.patch b/extra/cogl/git-fixes.patch new file mode 100644 index 000000000..2d16a1262 --- /dev/null +++ b/extra/cogl/git-fixes.patch @@ -0,0 +1,1948 @@ +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-atlas-texture.c b/cogl/cogl-atlas-texture.c +index 7f62efc..30dd319 100644 +--- a/cogl/cogl-atlas-texture.c ++++ b/cogl/cogl-atlas-texture.c +@@ -276,7 +276,8 @@ _cogl_atlas_texture_free (CoglAtlasTexture *atlas_tex) + { + _cogl_atlas_texture_remove_from_atlas (atlas_tex); + +- cogl_object_unref (atlas_tex->sub_texture); ++ if (atlas_tex->sub_texture) ++ cogl_object_unref (atlas_tex->sub_texture); + + /* Chain up */ + _cogl_texture_free (COGL_TEXTURE (atlas_tex)); +diff --git a/cogl/cogl-auto-texture.c b/cogl/cogl-auto-texture.c +index 6de2e32..9a5819d 100644 +--- a/cogl/cogl-auto-texture.c ++++ b/cogl/cogl-auto-texture.c +@@ -179,14 +179,6 @@ _cogl_texture_new_from_bitmap (CoglBitmap *bitmap, + &internal_error))) + return COGL_TEXTURE (atlas_tex); + +- if (cogl_error_matches (internal_error, +- COGL_SYSTEM_ERROR, +- COGL_SYSTEM_ERROR_NO_MEMORY)) +- { +- _cogl_propagate_error (error, internal_error); +- return NULL; +- } +- + cogl_error_free (internal_error); + internal_error = NULL; + +@@ -200,14 +192,6 @@ _cogl_texture_new_from_bitmap (CoglBitmap *bitmap, + internal_format, + &internal_error)); + +- if (cogl_error_matches (internal_error, +- COGL_SYSTEM_ERROR, +- COGL_SYSTEM_ERROR_NO_MEMORY)) +- { +- _cogl_propagate_error (error, internal_error); +- return NULL; +- } +- + if (!tex) + { + cogl_error_free (internal_error); +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-context.c b/cogl/cogl-context.c +index 175e69d..359e112 100644 +--- a/cogl/cogl-context.c ++++ b/cogl/cogl-context.c +@@ -133,7 +133,7 @@ cogl_context_new (CoglDisplay *display, + CoglError **error) + { + CoglContext *context; +- GLubyte default_texture_data[] = { 0xff, 0xff, 0xff, 0x0 }; ++ uint8_t default_texture_data[] = { 0xff, 0xff, 0xff, 0xff }; + CoglBitmap *default_texture_bitmap; + const CoglWinsysVtable *winsys; + int i; +diff --git a/cogl/cogl-error.c b/cogl/cogl-error.c +index 753e4c8..f72415b 100644 +--- a/cogl/cogl-error.c ++++ b/cogl/cogl-error.c +@@ -105,7 +105,10 @@ _cogl_propagate_error (CoglError **dest, + _COGL_RETURN_IF_FAIL (src != NULL); + + if (dest == NULL) +- cogl_error_free (src); ++ { ++ g_log (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, "%s", src->message); ++ cogl_error_free (src); ++ } + else if (*dest) + g_warning (ERROR_OVERWRITTEN_WARNING, src->message); + else +diff --git a/cogl/cogl-error.h b/cogl/cogl-error.h +index 1b6a951..ef6ee7e 100644 +--- a/cogl/cogl-error.h ++++ b/cogl/cogl-error.h +@@ -30,6 +30,8 @@ + + #include "cogl-types.h" + ++COGL_BEGIN_DECLS ++ + /** + * SECTION:cogl-error + * @short_description: A way for Cogl to throw exceptions +@@ -173,4 +175,6 @@ cogl_error_matches (CoglError *error, + #define COGL_GLIB_ERROR(COGL_ERROR) ((CoglError *)COGL_ERROR) + #endif + ++COGL_END_DECLS ++ + #endif /* __COGL_ERROR_H__ */ +diff --git a/cogl/cogl-fixed.c b/cogl/cogl-fixed.c +index e347605..4d92155 100644 +--- a/cogl/cogl-fixed.c ++++ b/cogl/cogl-fixed.c +@@ -30,6 +30,10 @@ + #include <glib-object.h> + #include <gobject/gvaluecollector.h> + ++#ifdef HAVE_FLOAT_WORD_ORDER ++#include <endian.h> ++#endif ++ + #include "cogl-fixed.h" + + /* pre-computed sin table for 1st quadrant +@@ -306,6 +310,7 @@ static const double _magic = 68719476736.0 * 1.5; + * + * FIXME - this should go inside the configure.ac + */ ++#ifdef HAVE_FLOAT_WORD_ORDER + #if (__FLOAT_WORD_ORDER == 1234) + #define _COGL_MAN 0 + #elif (__FLOAT_WORD_ORDER == 4321) +@@ -313,6 +318,9 @@ static const double _magic = 68719476736.0 * 1.5; + #else + #define COGL_NO_FAST_CONVERSIONS + #endif ++#else /* HAVE_FLOAT_WORD_ORDER */ ++#define COGL_NO_FAST_CONVERSIONS ++#endif /* HAVE_FLOAT_WORD_ORDER */ + + /* + * cogl_double_to_fixed : +@@ -629,7 +637,7 @@ cogl_fixed_sqrt (CoglFixed x) + /* + * Find the highest bit set + */ +-#if defined (__arm__) && !defined(__ARM_ARCH_4T__) ++#if defined (__arm__) && !defined(__ARM_ARCH_4T__) && !defined(__thumb__) + /* This actually requires at least arm v5, but gcc does not seem + * to set the architecture defines correctly, and it is I think + * very unlikely that anyone will want to use clutter on anything +@@ -807,7 +815,7 @@ CoglFixed + cogl_fixed_mul (CoglFixed a, + CoglFixed b) + { +-#ifdef __arm__ ++#if defined(__arm__) && !defined(__thumb__) + /* This provides about 12% speedeup on the gcc -O2 optimised + * C version + * +@@ -819,7 +827,7 @@ cogl_fixed_mul (CoglFixed a, + __asm__ ("smull %0, %1, %2, %3 \n" + "mov %0, %0, lsr %4 \n" + "add %1, %0, %1, lsl %5 \n" +- : "=r"(res_hi), "=r"(res_low) \ ++ : "=&r"(res_hi), "=&r"(res_low) \ + : "r"(a), "r"(b), "i"(COGL_FIXED_Q), "i"(32 - COGL_FIXED_Q)); + + return (CoglFixed) res_low; +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 <cogl/cogl-defines.h> ++ + #ifdef COGL_HAS_GTYPE_SUPPORT + #include <glib-object.h> + #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 ++ * <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-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 <http://www.gnu.org/licenses/>. ++ * ++ * ++ */ ++ ++#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 <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, +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/cogl/driver/gl/cogl-attribute-gl.c b/cogl/driver/gl/cogl-attribute-gl.c +index ba7e627..bd9c351 100644 +--- a/cogl/driver/gl/cogl-attribute-gl.c ++++ b/cogl/driver/gl/cogl-attribute-gl.c +@@ -251,17 +251,25 @@ setup_legacy_buffered_attribute (CoglContext *ctx, + case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY: + { + int layer_number = attribute->name_state->layer_number; ++ const CoglPipelineGetLayerFlags flags = ++ COGL_PIPELINE_GET_LAYER_NO_CREATE; + CoglPipelineLayer *layer = +- _cogl_pipeline_get_layer (pipeline, layer_number); +- int unit = _cogl_pipeline_layer_get_unit_index (layer); ++ _cogl_pipeline_get_layer_with_flags (pipeline, layer_number, flags); + +- _cogl_bitmask_set (&ctx->enable_texcoord_attributes_tmp, unit, TRUE); ++ if (layer) ++ { ++ int unit = _cogl_pipeline_layer_get_unit_index (layer); + +- GE (ctx, glClientActiveTexture (GL_TEXTURE0 + unit)); +- GE (ctx, glTexCoordPointer (attribute->d.buffered.n_components, +- attribute->d.buffered.type, +- attribute->d.buffered.stride, +- base + attribute->d.buffered.offset)); ++ _cogl_bitmask_set (&ctx->enable_texcoord_attributes_tmp, ++ unit, ++ TRUE); ++ ++ GE (ctx, glClientActiveTexture (GL_TEXTURE0 + unit)); ++ GE (ctx, glTexCoordPointer (attribute->d.buffered.n_components, ++ attribute->d.buffered.type, ++ attribute->d.buffered.stride, ++ base + attribute->d.buffered.offset)); ++ } + break; + } + case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY: +@@ -316,13 +324,24 @@ setup_legacy_const_attribute (CoglContext *ctx, + case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY: + { + int layer_number = attribute->name_state->layer_number; ++ const CoglPipelineGetLayerFlags flags = ++ COGL_PIPELINE_GET_LAYER_NO_CREATE; + CoglPipelineLayer *layer = +- _cogl_pipeline_get_layer (pipeline, layer_number); +- int unit = _cogl_pipeline_layer_get_unit_index (layer); ++ _cogl_pipeline_get_layer_with_flags (pipeline, ++ layer_number, ++ flags); + +- GE (ctx, glClientActiveTexture (GL_TEXTURE0 + unit)); ++ if (layer) ++ { ++ int unit = _cogl_pipeline_layer_get_unit_index (layer); ++ ++ GE (ctx, glClientActiveTexture (GL_TEXTURE0 + unit)); + +- GE (ctx, glMultiTexCoord4f (vector[0], vector[1], vector[2], vector[3])); ++ GE (ctx, glMultiTexCoord4f (vector[0], ++ vector[1], ++ vector[2], ++ vector[3])); ++ } + break; + } + case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY: +diff --git a/cogl/winsys/cogl-winsys-egl-wayland.c b/cogl/winsys/cogl-winsys-egl-wayland.c +index feeb529..156ecb9 100644 +--- a/cogl/winsys/cogl-winsys-egl-wayland.c ++++ b/cogl/winsys/cogl-winsys-egl-wayland.c +@@ -370,12 +370,22 @@ _cogl_winsys_egl_onscreen_deinit (CoglOnscreen *onscreen) + wayland_onscreen->wayland_egl_native_window = NULL; + } + ++ /* NB: The wayland protocol docs explicitly state that ++ * "wl_shell_surface_destroy() must be called before destroying the ++ * wl_surface object." ... */ ++ if (wayland_onscreen->wayland_shell_surface) ++ { ++ wl_shell_surface_destroy (wayland_onscreen->wayland_shell_surface); ++ wayland_onscreen->wayland_shell_surface = NULL; ++ } ++ + if (wayland_onscreen->wayland_surface) + { + wl_surface_destroy (wayland_onscreen->wayland_surface); + wayland_onscreen->wayland_surface = NULL; + } + ++ + g_slice_free (CoglOnscreenWayland, wayland_onscreen); + } + +diff --git a/configure.ac b/configure.ac +index 43bf407..3d57980 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -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" + ], + [ +@@ -950,7 +957,7 @@ AS_IF([test "x$enable_kms_egl_platform" = "xyes"], + GBM_VERSION=`$PKG_CONFIG --modversion gbm` + GBM_MAJOR=`echo $GBM_VERSION | cut -d'.' -f1` + GBM_MINOR=`echo $GBM_VERSION | cut -d'.' -f2` +- GBM_MICRO=`echo $GBM_VERSION | cut -d'.' -f3` ++ GBM_MICRO=`echo $GBM_VERSION | cut -d'.' -f3 | sed 's/-.*//'` + + AC_DEFINE_UNQUOTED([COGL_GBM_MAJOR], [$GBM_MAJOR], [The major version for libgbm]) + AC_DEFINE_UNQUOTED([COGL_GBM_MINOR], [$GBM_MINOR], [The minor version for libgbm]) +@@ -1160,7 +1167,10 @@ dnl ================================================================ + AC_PATH_X + AC_HEADER_STDC + AC_CHECK_HEADERS(fcntl.h limits.h unistd.h) +- ++AC_CHECK_HEADER([endian.h], ++ [AC_CHECK_DECL([__FLOAT_WORD_ORDER], ++ AC_DEFINE([HAVE_FLOAT_WORD_ORDER], [1], ++ [Has the __FLOAT_WORD_ORDER macro]))]) + + dnl ================================================================ + dnl Checks for library functions. +@@ -1173,6 +1183,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 <math.h> +@@ -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..238f34c 100644 +--- a/examples/cogland.c ++++ b/examples/cogland.c +@@ -8,6 +8,10 @@ + + #include <wayland-server.h> + ++#ifdef COGL_HAS_XLIB_SUPPORT ++#include <cogl/cogl-xlib.h> ++#endif ++ + typedef struct _CoglandCompositor CoglandCompositor; + + typedef struct +@@ -25,7 +29,7 @@ typedef struct + { + CoglandCompositor *compositor; + +- struct wl_surface wayland_surface; ++ struct wl_resource resource; + int x; + int y; + struct wl_buffer *buffer; +@@ -38,6 +42,7 @@ typedef struct + struct + { + /* wl_surface.attach */ ++ CoglBool newly_attached; + struct wl_buffer *buffer; + struct wl_listener buffer_destroy_listener; + int32_t sx; +@@ -93,7 +98,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 +340,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 +386,8 @@ shm_buffer_damaged (CoglandSurface *surface, + stride, + data); + } ++ ++ cogland_queue_redraw (surface->compositor); + } + + static void +@@ -453,6 +460,7 @@ cogland_surface_attach (struct wl_client *wayland_client, + surface->pending.sx = sx; + surface->pending.sy = sy; + surface->pending.buffer = buffer; ++ surface->pending.newly_attached = TRUE; + + if (buffer) + wl_signal_add (&buffer->resource.destroy_signal, +@@ -522,7 +530,8 @@ cogland_surface_commit (struct wl_client *client, + CoglandCompositor *compositor = surface->compositor; + + /* wl_surface.attach */ +- if (surface->buffer != surface->pending.buffer) ++ if (surface->pending.newly_attached && ++ surface->buffer != surface->pending.buffer) + { + CoglError *error = NULL; + +@@ -546,16 +555,19 @@ 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; ++ surface->pending.newly_attached = FALSE; + + /* wl_surface.damage */ + if (surface->buffer && +- wl_buffer_is_shm (surface->buffer) && + surface->texture && + !region_is_empty (&surface->pending.damage)) + { +@@ -571,11 +583,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 +595,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 +624,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); +@@ -647,13 +660,13 @@ cogland_compositor_create_surface (struct wl_client *wayland_client, + + surface->compositor = compositor; + +- surface->wayland_surface.resource.destroy = ++ surface->resource.destroy = + cogland_surface_resource_destroy_cb; +- surface->wayland_surface.resource.object.id = id; +- surface->wayland_surface.resource.object.interface = &wl_surface_interface; +- surface->wayland_surface.resource.object.implementation = ++ surface->resource.object.id = id; ++ surface->resource.object.interface = &wl_surface_interface; ++ surface->resource.object.implementation = + (void (**)(void)) &cogland_surface_interface; +- surface->wayland_surface.resource.data = surface; ++ surface->resource.data = surface; + + surface->buffer_destroy_listener.notify = + surface_handle_buffer_destroy; +@@ -663,7 +676,7 @@ cogland_compositor_create_surface (struct wl_client *wayland_client, + wl_list_init (&surface->pending.frame_callback_list); + region_init (&surface->pending.damage); + +- wl_client_add_resource (wayland_client, &surface->wayland_surface.resource); ++ wl_client_add_resource (wayland_client, &surface->resource); + + compositor->surfaces = g_list_prepend (compositor->surfaces, + surface); +@@ -970,7 +983,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 +993,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; +@@ -989,7 +1003,7 @@ get_shell_surface (struct wl_client *client, + + shell_surface->surface = surface; + shell_surface->surface_destroy_listener.notify = shell_handle_surface_destroy; +- wl_signal_add (&surface->wayland_surface.resource.destroy_signal, ++ wl_signal_add (&surface->resource.destroy_signal, + &shell_surface->surface_destroy_listener); + + surface->has_shell_surface = TRUE; +@@ -1012,6 +1026,109 @@ 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; ++} ++ ++#ifdef COGL_HAS_XLIB_SUPPORT ++ ++static CoglFilterReturn ++x_event_cb (XEvent *event, ++ void *data) ++{ ++ CoglandCompositor *compositor = data; ++ ++ if (event->type == Expose) ++ cogland_queue_redraw (compositor); ++ ++ return COGL_FILTER_CONTINUE; ++} ++ ++#endif /* COGL_HAS_XLIB_SUPPORT */ ++ ++static gboolean ++timeout_cb (void *data) ++{ ++ cogland_queue_redraw (data); ++ ++ return TRUE; ++} ++ ++static void ++init_redraws (CoglandCompositor *compositor) ++{ ++#ifdef COGL_HAS_XLIB_SUPPORT ++ CoglDisplay *display = cogl_context_get_display (compositor->cogl_context); ++ CoglRenderer *renderer = cogl_display_get_renderer (display); ++ CoglWinsysID winsys = cogl_renderer_get_winsys_id (renderer); ++ ++ /* If Cogl is using X then we can listen for Expose events to know ++ * when to repaint the window. Otherwise we don't have any code to ++ * know when the contents of the window is dirty so we'll just ++ * redraw constantly */ ++ switch (winsys) ++ { ++ case COGL_WINSYS_ID_GLX: ++ case COGL_WINSYS_ID_EGL_XLIB: ++ { ++ Display *display = cogl_xlib_renderer_get_display (renderer); ++ GList *l; ++ ++ for (l = compositor->outputs; l; l = l->next) ++ { ++ CoglandOutput *output = l->data; ++ XWindowAttributes win_attribs; ++ Window win; ++ ++ win = cogl_x11_onscreen_get_window_xid (output->onscreen); ++ if (XGetWindowAttributes (display, win, &win_attribs)) ++ { ++ XSelectInput (display, ++ win, ++ win_attribs.your_event_mask | ExposureMask); ++ cogl_xlib_renderer_add_filter (renderer, ++ x_event_cb, ++ compositor); ++ ++ } ++ } ++ } ++ return; ++ ++ default: ++ break; ++ } ++#endif /* COGL_HAS_XLIB_SUPPORT */ ++ ++ g_timeout_add (16, timeout_cb, compositor); ++} ++ + int + main (int argc, char **argv) + { +@@ -1020,7 +1137,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 +1172,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; +@@ -1101,7 +1235,7 @@ main (int argc, char **argv) + + g_source_attach (cogl_source, NULL); + +- cogland_queue_redraw (&compositor); ++ init_redraws (&compositor); + + g_main_loop_run (loop); + +diff --git a/tests/conform/Makefile.am b/tests/conform/Makefile.am +index 69a460d..d4062f2 100644 +--- a/tests/conform/Makefile.am ++++ b/tests/conform/Makefile.am +@@ -65,6 +65,8 @@ test_sources = \ + test-framebuffer-get-bits.c \ + test-primitive-and-journal.c \ + test-copy-replace-texture.c \ ++ test-pipeline-cache-unrefs-texture.c \ ++ test-texture-no-allocate.c \ + $(NULL) + + test_conformance_SOURCES = $(common_sources) $(test_sources) +@@ -131,7 +133,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..c5a5d4c 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); +@@ -130,6 +132,8 @@ main (int argc, char **argv) + + ADD_TEST (test_euler_quaternion, 0, 0); + ++ ADD_TEST (test_texture_no_allocate, 0, 0); ++ + g_printerr ("Unknown test name \"%s\"\n", argv[1]); + + return 1; +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 <cogl/cogl.h> ++ ++#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/conform/test-texture-no-allocate.c b/tests/conform/test-texture-no-allocate.c +new file mode 100644 +index 0000000..fccb742 +--- /dev/null ++++ b/tests/conform/test-texture-no-allocate.c +@@ -0,0 +1,80 @@ ++#include <cogl/cogl.h> ++ ++#include "test-utils.h" ++ ++/* Tests that the various texture types can be freed without being ++ * allocated */ ++ ++/* Texture size that is probably to big to fit within the texture ++ * limits */ ++#define BIG_TEX_WIDTH 16384 ++#define BIG_TEX_HEIGHT 128 ++ ++void ++test_texture_no_allocate (void) ++{ ++ uint8_t *tex_data; ++ CoglTexture *texture; ++ CoglTexture2D *texture_2d; ++ ++ tex_data = g_malloc (BIG_TEX_WIDTH * BIG_TEX_HEIGHT * 4); ++ ++ /* NB: if we make the atlas and sliced texture APIs public then this ++ * could changed to explicitly use that instead of the magic texture ++ * API */ ++ ++ /* Try to create an atlas texture that is too big so it will ++ * internally be freed without allocating */ ++ texture = cogl_texture_new_from_data (BIG_TEX_WIDTH, ++ BIG_TEX_HEIGHT, ++ COGL_TEXTURE_NONE, /* flags */ ++ /* format */ ++ COGL_PIXEL_FORMAT_RGBA_8888_PRE, ++ /* internal format */ ++ COGL_PIXEL_FORMAT_ANY, ++ /* rowstride */ ++ BIG_TEX_WIDTH * 4, ++ tex_data); ++ ++ g_free (tex_data); ++ ++ /* It's ok if this causes an error, we just don't want it to ++ * crash */ ++ ++ if (texture) ++ cogl_object_unref (texture); ++ ++ /* Try to create a sliced texture without allocating it */ ++ texture = cogl_texture_new_with_size (BIG_TEX_WIDTH, ++ BIG_TEX_HEIGHT, ++ COGL_TEXTURE_NO_ATLAS, ++ COGL_PIXEL_FORMAT_RGBA_8888_PRE); ++ cogl_object_unref (texture); ++ ++ /* 2D texture */ ++ texture_2d = cogl_texture_2d_new_with_size (test_ctx, ++ 64, 64, ++ COGL_PIXEL_FORMAT_RGBA_8888_PRE); ++ cogl_object_unref (texture_2d); ++ ++ /* 3D texture */ ++ if (cogl_has_feature (test_ctx, COGL_FEATURE_ID_TEXTURE_3D)) ++ { ++ CoglTexture3D *texture_3d = ++ cogl_texture_3d_new_with_size (test_ctx, ++ 64, 64, 64, ++ COGL_PIXEL_FORMAT_RGBA_8888_PRE); ++ cogl_object_unref (texture_3d); ++ } ++ ++ /* Rectangle texture */ ++ if (cogl_has_feature (test_ctx, COGL_FEATURE_ID_TEXTURE_RECTANGLE)) ++ { ++ CoglTextureRectangle *texture_rect = ++ cogl_texture_rectangle_new_with_size (test_ctx, ++ 64, 64, ++ COGL_PIXEL_FORMAT_RGBA_8888_PRE, ++ NULL /* error */); ++ cogl_object_unref (texture_rect); ++ } ++} +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) |