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.
This commit is contained in:
Robert Bragg 2010-05-27 23:31:40 +01:00
parent 0f32fb4acd
commit 7bcea1c64e
4 changed files with 245 additions and 144 deletions

View File

@ -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 <http://www.gnu.org/licenses/>.
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*
*
*/
/* 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 */

183
cogl/cogl-object.h Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*
*
*/
#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 */

View File

@ -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:
*

View File

@ -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
*/