summaryrefslogtreecommitdiff
path: root/cogl/cogl-object.c
diff options
context:
space:
mode:
authorRobert Bragg <robert@linux.intel.com>2010-05-27 22:24:56 +0100
committerRobert Bragg <robert@linux.intel.com>2010-06-04 14:44:15 +0100
commit5af3ead3a2bbd18f4b1ee35eabffd20d740749c1 (patch)
treec738f5c82f5ea0e6fc3e2818d6b4e1f980fbbc22 /cogl/cogl-object.c
parentef08c6369a0bb2a261fa16bf4323a5d524d5d788 (diff)
downloadcogl-5af3ead3a2bbd18f4b1ee35eabffd20d740749c1.tar.gz
CoglObject: Adds cogl_object_{get,set}_user_data
This provides a mechanism for associating private data with any CoglObject. We expect Clutter will use this to associate weak materials with normal materials.
Diffstat (limited to 'cogl/cogl-object.c')
-rw-r--r--cogl/cogl-object.c246
1 files changed, 246 insertions, 0 deletions
diff --git a/cogl/cogl-object.c b/cogl/cogl-object.c
new file mode 100644
index 00000000..aa11cef2
--- /dev/null
+++ b/cogl/cogl-object.c
@@ -0,0 +1,246 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2007,2008,2009,2010 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:
+ * Robert Bragg <robert@linux.intel.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <string.h>
+
+#include "cogl-types.h"
+#include "cogl-object-private.h"
+
+void *
+cogl_object_ref (void *object)
+{
+ CoglObject *obj = object;
+
+ g_return_val_if_fail (object != NULL, NULL);
+
+ obj->ref_count++;
+ return object;
+}
+
+CoglHandle
+cogl_handle_ref (CoglHandle handle)
+{
+ return cogl_object_ref (handle);
+}
+
+void
+cogl_object_unref (void *object)
+{
+ CoglObject *obj = object;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (obj->ref_count > 0);
+
+ if (--obj->ref_count < 1)
+ {
+ void (*free_func)(void *obj);
+
+ if (obj->n_user_data_entries)
+ {
+ int i;
+ int count = MIN (obj->n_user_data_entries,
+ COGL_OBJECT_N_PRE_ALLOCATED_USER_DATA_ENTRIES);
+
+ for (i = 0; i < count; i++)
+ {
+ CoglUserDataEntry *entry = &obj->user_data_entry[i];
+ if (entry->destroy)
+ entry->destroy (entry->user_data);
+ }
+
+ if (obj->user_data_array != NULL)
+ {
+ for (i = 0; i < obj->user_data_array->len; i++)
+ {
+ CoglUserDataEntry *entry =
+ &g_array_index (obj->user_data_array,
+ CoglUserDataEntry, i);
+
+ if (entry->destroy)
+ entry->destroy (entry->user_data);
+ }
+ }
+
+ g_array_free (obj->user_data_array, TRUE);
+ }
+
+ COGL_OBJECT_DEBUG_FREE (obj);
+ free_func = obj->klass->virt_free;
+ free_func (obj);
+ }
+}
+
+void
+cogl_handle_unref (CoglHandle handle)
+{
+ cogl_object_unref (handle);
+}
+
+GType
+cogl_object_get_type (void)
+{
+ static GType our_type = 0;
+
+ /* XXX: We are keeping the "CoglHandle" name for now incase it would
+ * break bindings to change to "CoglObject" */
+ if (G_UNLIKELY (our_type == 0))
+ our_type = g_boxed_type_register_static (g_intern_static_string ("CoglHandle"),
+ (GBoxedCopyFunc) cogl_object_ref,
+ (GBoxedFreeFunc) cogl_object_unref);
+
+ return our_type;
+}
+
+GType
+cogl_handle_get_type (void)
+{
+ return cogl_object_get_type ();
+}
+
+/* XXX: Unlike for cogl_object_get_user_data this code will return
+ * an empty entry if available and no entry for the given key can be
+ * found. */
+static CoglUserDataEntry *
+_cogl_object_find_entry (CoglObject *object, CoglUserDataKey *key)
+{
+ CoglUserDataEntry *entry = NULL;
+ int count;
+ int i;
+
+ count = MIN (object->n_user_data_entries,
+ COGL_OBJECT_N_PRE_ALLOCATED_USER_DATA_ENTRIES);
+
+ for (i = 0; i < count; i++)
+ {
+ CoglUserDataEntry *current = &object->user_data_entry[i];
+ if (current->key == key)
+ return current;
+ if (current->user_data == NULL)
+ entry = current;
+ }
+
+ if (G_UNLIKELY (object->user_data_array != NULL))
+ {
+ for (i = 0; i < object->user_data_array->len; i++)
+ {
+ CoglUserDataEntry *current =
+ &g_array_index (object->user_data_array, CoglUserDataEntry, i);
+
+ if (current->key == key)
+ return current;
+ if (current->user_data == NULL)
+ entry = current;
+ }
+ }
+
+ return entry;
+}
+
+void
+cogl_object_set_user_data (CoglObject *object,
+ CoglUserDataKey *key,
+ void *user_data,
+ CoglUserDataDestroyCallback destroy)
+{
+ CoglUserDataEntry new_entry;
+ CoglUserDataEntry *entry;
+
+ if (user_data)
+ {
+ new_entry.key = key;
+ new_entry.user_data = user_data;
+ new_entry.destroy = destroy;
+ }
+ else
+ memset (&new_entry, 0, sizeof (new_entry));
+
+ entry = _cogl_object_find_entry (object, key);
+ if (entry)
+ {
+ if (G_LIKELY (entry->destroy))
+ entry->destroy (entry->user_data);
+ }
+ else
+ {
+ if (G_LIKELY (object->n_user_data_entries <
+ COGL_OBJECT_N_PRE_ALLOCATED_USER_DATA_ENTRIES))
+ entry = &object->user_data_entry[object->n_user_data_entries++];
+ else
+ {
+ if (G_UNLIKELY (object->user_data_array == NULL))
+ {
+ object->user_data_array =
+ g_array_new (FALSE, FALSE, sizeof (CoglUserDataEntry));
+ }
+
+ g_array_set_size (object->user_data_array,
+ object->user_data_array->len + 1);
+ entry =
+ &g_array_index (object->user_data_array, CoglUserDataEntry,
+ object->user_data_array->len - 1);
+
+ object->n_user_data_entries++;
+ }
+ }
+
+ *entry = new_entry;
+}
+
+void *
+cogl_object_get_user_data (CoglObject *object, CoglUserDataKey *key)
+{
+ int count;
+ int i;
+
+ count = MIN (object->n_user_data_entries,
+ COGL_OBJECT_N_PRE_ALLOCATED_USER_DATA_ENTRIES);
+
+ for (i = 0; i < count; i++)
+ {
+ CoglUserDataEntry *entry = &object->user_data_entry[i];
+ if (entry->key == key)
+ return entry->user_data;
+ }
+
+ if (object->user_data_array != NULL)
+ {
+ for (i = 0; i < object->user_data_array->len; i++)
+ {
+ CoglUserDataEntry *entry =
+ &g_array_index (object->user_data_array, CoglUserDataEntry, i);
+
+ if (entry->key == key)
+ return entry->user_data;
+ }
+ }
+
+ return NULL;
+}
+