From 7bcea1c64eede09582cf0bbfafaec48cac42744c Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Thu, 27 May 2010 23:31:40 +0100 Subject: [PATCH] Start eradicating the CoglHandle typedef CoglHandle is a common source of complaints and confusion because people expect a "handle" to be some form of integer type with some indirection to lookup the corresponding objects as opposed to a direct pointer. This patch starts by renaming CoglHandle to CoglObject * and creating corresponding cogl_object_ APIs to replace the cogl_handle ones. The next step though is to remove all use of CoglHandle in the Cogl APIs and replace with strongly typed pointer types such as CoglMaterial * or CoglTexture * etc also all occurrences of COGL_INVALID_HANDLE can just use NULL instead. After this we will consider switching to GTypeInstance internally so we can have inheritance for our types and hopefully improve how we handle bindings. Note all these changes will be done in a way that maintains the API and ABI. --- cogl/cogl-handle.h | 140 +++------------------------------- cogl/cogl-object.h | 183 +++++++++++++++++++++++++++++++++++++++++++++ cogl/cogl-types.h | 21 ++++++ cogl/cogl-util.c | 45 +++++++---- 4 files changed, 245 insertions(+), 144 deletions(-) create mode 100644 cogl/cogl-object.h diff --git a/cogl/cogl-handle.h b/cogl/cogl-handle.h index 576598e5d..de63efb1b 100644 --- a/cogl/cogl-handle.h +++ b/cogl/cogl-handle.h @@ -3,7 +3,7 @@ * * An object oriented GL/GLES Abstraction/Utility Layer * - * Copyright (C) 2008,2009 Intel Corporation. + * Copyright (C) 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 @@ -16,142 +16,20 @@ * 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 . + * License along with this library. If not, see + * . * * */ +/* This file is just kept for compatability while we eradicate + * CoglHandle + */ + #ifndef __COGL_HANDLE_H #define __COGL_HANDLE_H -typedef struct _CoglHandleClass -{ - GQuark type; - void *virt_free; -} CoglHandleClass; - -/* All Cogl objects inherit from this base object by adding a member: - * - * CoglHandleObject _parent; - * - * at the top of its main structure. This structure is initialized - * when you call _cogl_#type_name#_handle_new (new_object); - */ -typedef struct _CoglHandleObject -{ - unsigned int ref_count; - CoglHandleClass *klass; -} CoglHandleObject; - -/* Helper macro to encapsulate the common code for COGL reference - counted handles */ - -#ifdef COGL_HANDLE_DEBUG - -#define _COGL_HANDLE_DEBUG_NEW(type_name, obj) \ - COGL_NOTE (HANDLE, "COGL " G_STRINGIFY (type_name) " NEW %p %i", \ - (obj), (obj)->ref_count) - -#define _COGL_HANDLE_DEBUG_REF(type_name, handle) G_STMT_START { \ - CoglHandleObject *__obj = (CoglHandleObject *)handle; \ - COGL_NOTE (HANDLE, "COGL %s REF %p %i", \ - g_quark_to_string ((__obj)->klass->type), \ - (__obj), (__obj)->ref_count); } G_STMT_END - -#define _COGL_HANDLE_DEBUG_UNREF(type_name, handle) G_STMT_START { \ - CoglHandleObject *__obj = (CoglHandleObject *)handle; \ - COGL_NOTE (HANDLE, "COGL %s UNREF %p %i", \ - g_quark_to_string ((__obj)->klass->type), \ - (__obj), (__obj)->ref_count - 1); } G_STMT_END - -#define COGL_HANDLE_DEBUG_FREE(obj) \ - COGL_NOTE (HANDLE, "COGL %s FREE %p", \ - g_quark_to_string ((obj)->klass->type), (obj)) - -#else /* !COGL_HANDLE_DEBUG */ - -#define _COGL_HANDLE_DEBUG_NEW(type_name, obj) -#define _COGL_HANDLE_DEBUG_REF(type_name, obj) -#define _COGL_HANDLE_DEBUG_UNREF(type_name, obj) -#define COGL_HANDLE_DEBUG_FREE(obj) - -#endif /* COGL_HANDLE_DEBUG */ - -#define COGL_HANDLE_DEFINE(TypeName, type_name) \ - \ -static CoglHandleClass _cogl_##type_name##_class; \ - \ -GQuark \ -_cogl_handle_##type_name##_get_type (void) \ -{ \ - static GQuark type = 0; \ - if (!type) \ - type = g_quark_from_static_string ("Cogl"#TypeName); \ - return type; \ -} \ - \ -static CoglHandle \ -_cogl_##type_name##_handle_new (Cogl##TypeName *new_obj) \ -{ \ - CoglHandleObject *obj = (CoglHandleObject *)&new_obj->_parent;\ - obj->ref_count = 1; \ - \ - obj->klass = &_cogl_##type_name##_class; \ - if (!obj->klass->type) \ - { \ - obj->klass->type = _cogl_handle_##type_name##_get_type ();\ - obj->klass->virt_free = _cogl_##type_name##_free; \ - } \ - \ - _COGL_HANDLE_DEBUG_NEW (TypeName, obj); \ - return (CoglHandle) new_obj; \ -} \ - \ -Cogl##TypeName * \ -_cogl_##type_name##_pointer_from_handle (CoglHandle handle) \ -{ \ - return (Cogl##TypeName *) handle; \ -} \ - \ -gboolean \ -cogl_is_##type_name (CoglHandle handle) \ -{ \ - CoglHandleObject *obj = (CoglHandleObject *)handle; \ - \ - if (handle == COGL_INVALID_HANDLE) \ - return FALSE; \ - \ - return (obj->klass->type == \ - _cogl_handle_##type_name##_get_type ()); \ -} \ - \ -CoglHandle G_GNUC_DEPRECATED \ -cogl_##type_name##_ref (CoglHandle handle) \ -{ \ - if (!cogl_is_##type_name (handle)) \ - return COGL_INVALID_HANDLE; \ - \ - _COGL_HANDLE_DEBUG_REF (TypeName, handle); \ - \ - cogl_handle_ref (handle); \ - \ - return handle; \ -} \ - \ -void G_GNUC_DEPRECATED \ -cogl_##type_name##_unref (CoglHandle handle) \ -{ \ - if (!cogl_is_##type_name (handle)) \ - { \ - g_warning (G_STRINGIFY (cogl_##type_name##_unref) \ - ": Ignoring unref of Cogl handle " \ - "due to type mismatch"); \ - return; \ - } \ - \ - _COGL_HANDLE_DEBUG_UNREF (TypeName, handle); \ - \ - cogl_handle_unref (handle); \ -} +#include "cogl-object.h" #endif /* __COGL_HANDLE_H */ + diff --git a/cogl/cogl-object.h b/cogl/cogl-object.h new file mode 100644 index 000000000..bfa660b5e --- /dev/null +++ b/cogl/cogl-object.h @@ -0,0 +1,183 @@ +/* + * Cogl + * + * An object oriented GL/GLES Abstraction/Utility Layer + * + * Copyright (C) 2008,2009 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_OBJECT_H +#define __COGL_OBJECT_H + +/* For compatability until all components have been converted */ +typedef struct _CoglObjectClass CoglHandleClass; +typedef struct _CoglObject CoglHandleObject; + +typedef struct _CoglObjectClass +{ + GQuark type; + void *virt_free; +} CoglObjectClass; + +/* All Cogl objects inherit from this base object by adding a member: + * + * CoglObject _parent; + * + * at the top of its main structure. This structure is initialized + * when you call _cogl_#type_name#_object_new (new_object); + */ +typedef struct _CoglObject +{ + unsigned int ref_count; + CoglObjectClass *klass; +} CoglObject; + +/* Helper macro to encapsulate the common code for COGL reference + counted objects */ + +#ifdef COGL_OBJECT_DEBUG + +#define _COGL_OBJECT_DEBUG_NEW(type_name, obj) \ + COGL_NOTE (HANDLE, "COGL " G_STRINGIFY (type_name) " NEW %p %i", \ + (obj), (obj)->ref_count) + +#define _COGL_OBJECT_DEBUG_REF(type_name, object) G_STMT_START { \ + CoglObject *__obj = (CoglObject *)object; \ + COGL_NOTE (HANDLE, "COGL %s REF %p %i", \ + g_quark_to_string ((__obj)->klass->type), \ + (__obj), (__obj)->ref_count); } G_STMT_END + +#define _COGL_OBJECT_DEBUG_UNREF(type_name, object) G_STMT_START { \ + CoglObject *__obj = (CoglObject *)object; \ + COGL_NOTE (HANDLE, "COGL %s UNREF %p %i", \ + g_quark_to_string ((__obj)->klass->type), \ + (__obj), (__obj)->ref_count - 1); } G_STMT_END + +#define COGL_OBJECT_DEBUG_FREE(obj) \ + COGL_NOTE (HANDLE, "COGL %s FREE %p", \ + g_quark_to_string ((obj)->klass->type), (obj)) + +#else /* !COGL_OBJECT_DEBUG */ + +#define _COGL_OBJECT_DEBUG_NEW(type_name, obj) +#define _COGL_OBJECT_DEBUG_REF(type_name, obj) +#define _COGL_OBJECT_DEBUG_UNREF(type_name, obj) +#define COGL_OBJECT_DEBUG_FREE(obj) + +#endif /* COGL_OBJECT_DEBUG */ + +/* For temporary compatability */ +#define _COGL_HANDLE_DEBUG_NEW _COGL_OBJECT_DEBUG_NEW +#define _COGL_HANDLE_DEBUG_REF _COGL_OBJECT_DEBUG_REF +#define _COGL_HANDLE_DEBUG_UNREF _COGL_OBJECT_DEBUG_UNREF +#define COGL_HANDLE_DEBUG_FREE COGL_OBJECT_DEBUG_FREE + +#define COGL_OBJECT_DEFINE(TypeName, type_name) \ + \ +static CoglObjectClass _cogl_##type_name##_class; \ + \ +GQuark \ +_cogl_object_##type_name##_get_type (void) \ +{ \ + static GQuark type = 0; \ + if (!type) \ + type = g_quark_from_static_string ("Cogl"#TypeName); \ + return type; \ +} \ + \ +GQuark \ +_cogl_handle_##type_name##_get_type (void) \ +{ \ + return _cogl_object_##type_name##_get_type (); \ +} \ + \ +static Cogl##TypeName * \ +_cogl_##type_name##_object_new (Cogl##TypeName *new_obj) \ +{ \ + CoglObject *obj = (CoglObject *)&new_obj->_parent;\ + obj->ref_count = 1; \ + \ + obj->klass = &_cogl_##type_name##_class; \ + if (!obj->klass->type) \ + { \ + obj->klass->type = _cogl_object_##type_name##_get_type ();\ + obj->klass->virt_free = _cogl_##type_name##_free; \ + } \ + \ + _COGL_OBJECT_DEBUG_NEW (TypeName, obj); \ + return new_obj; \ +} \ + \ +static Cogl##TypeName * \ +_cogl_##type_name##_handle_new (CoglHandle handle) \ +{ \ + return _cogl_##type_name##_object_new (handle); \ +} \ + \ +Cogl##TypeName * \ +_cogl_##type_name##_pointer_from_handle (CoglHandle handle) \ +{ \ + return handle; \ +} \ + \ +gboolean \ +cogl_is_##type_name (CoglHandle object) \ +{ \ + CoglObject *obj = object; \ + \ + if (object == NULL) \ + return FALSE; \ + \ + return (obj->klass->type == \ + _cogl_object_##type_name##_get_type ()); \ +} \ + \ +void * G_GNUC_DEPRECATED \ +cogl_##type_name##_ref (void *object) \ +{ \ + if (!cogl_is_##type_name (object)) \ + return NULL; \ + \ + _COGL_OBJECT_DEBUG_REF (TypeName, object); \ + \ + cogl_handle_ref (object); \ + \ + return object; \ +} \ + \ +void G_GNUC_DEPRECATED \ +cogl_##type_name##_unref (void *object) \ +{ \ + if (!cogl_is_##type_name (object)) \ + { \ + g_warning (G_STRINGIFY (cogl_##type_name##_unref) \ + ": Ignoring unref of Cogl handle " \ + "due to type mismatch"); \ + return; \ + } \ + \ + _COGL_OBJECT_DEBUG_UNREF (TypeName, object); \ + \ + cogl_handle_unref (object); \ +} + +/* For temporary compatability */ +#define COGL_HANDLE_DEFINE COGL_OBJECT_DEFINE + +#endif /* __COGL_OBJECT_H */ + diff --git a/cogl/cogl-types.h b/cogl/cogl-types.h index 547ed129a..61a3eff7b 100644 --- a/cogl/cogl-types.h +++ b/cogl/cogl-types.h @@ -83,6 +83,27 @@ cogl_handle_ref (CoglHandle handle); void cogl_handle_unref (CoglHandle Handle); +/** + * cogl_handle_ref: + * @object: a #CoglObject + * + * Increases the reference count of @handle by 1 + * + * Returns: the @object, with its reference count increased + */ +void * +cogl_object_ref (void *object); + +/** + * cogl_handle_unref: + * @object: a #CoglObject + * + * Drecreases the reference count of @object by 1; if the reference + * count reaches 0, the resources allocated by @object will be freed + */ +void +cogl_object_unref (void *object); + /** * CoglFuncPtr: * diff --git a/cogl/cogl-util.c b/cogl/cogl-util.c index 622b78505..cc28b08e6 100644 --- a/cogl/cogl-util.c +++ b/cogl/cogl-util.c @@ -61,48 +61,67 @@ cogl_util_next_p2 (int a) /* gtypes */ +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) { - CoglHandleObject *obj = (CoglHandleObject *)handle; - - g_return_val_if_fail (handle != COGL_INVALID_HANDLE, COGL_INVALID_HANDLE); - - obj->ref_count++; - return handle; + return cogl_object_ref (handle); } void -cogl_handle_unref (CoglHandle handle) +cogl_object_unref (void *object) { - CoglHandleObject *obj = (CoglHandleObject *)handle; + CoglObject *obj = object; - g_return_if_fail (handle != COGL_INVALID_HANDLE); + g_return_if_fail (object != NULL); g_return_if_fail (obj->ref_count > 0); if (--obj->ref_count < 1) { void (*free_func)(void *obj); - COGL_HANDLE_DEBUG_FREE (obj); + 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_handle_get_type (void) +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_handle_ref, - (GBoxedFreeFunc) cogl_handle_unref); + (GBoxedCopyFunc) cogl_object_ref, + (GBoxedFreeFunc) cogl_object_unref); return our_type; } +GType +cogl_handle_get_type (void) +{ + return cogl_object_get_type (); +} /* * CoglFixed */