shader: Don't notify properties when finalizing shaders

clutter_shader_finalize() was calling clutter_shader_release() which in
turn notifies "compiled". GObject was complaining that we were trying to
_ref() an object that was in _finalize().

 #0  g_log (log_domain=0x3e15c4 "GLib-GObject", log_level=G_LOG_LEVEL_CRITICAL,
     format=0x76c938 "%s: assertion `%s' failed") at gmessages.h:97
 #1  0x0070777d in g_return_if_fail_warning (
     log_domain=0x3e15c4 "GLib-GObject",
     pretty_function=0x3e37a4 "g_object_ref",
     expression=0x3e2a00 "object->ref_count > 0") at gmessages.c:586
 #2  0x003b862b in g_object_ref (_object=0x8567af0) at gobject.c:2615
 #3  0x003bd238 in g_object_notify_by_pspec (object=0x8567af0, pspec=0x87ea2f0)
     at gobject.c:1075
 #4  0x00b6500b in clutter_shader_release (shader=0x8567af0)
     at ./clutter-shader.c:612
 #5  0x00b659b9 in clutter_shader_finalize (object=0x8567af0)
     at ./clutter-shader.c:107

Then, let's split release in two, with an _internal() version that does
not notify "compiled" and use it from dispose (as the object is still
usable after a call to release_internal().

http://bugzilla.clutter-project.org/show_bug.cgi?id=2512
This commit is contained in:
Damien Lespiau 2011-01-11 10:23:59 +00:00 committed by Emmanuele Bassi
parent 3625adb9d8
commit f2080f099e

View File

@ -95,6 +95,31 @@ static GParamSpec *obj_props[PROP_LAST];
G_DEFINE_TYPE (ClutterShader, clutter_shader, G_TYPE_OBJECT);
static inline void
clutter_shader_release_internal (ClutterShader *shader)
{
ClutterShaderPrivate *priv = shader->priv;
if (!priv->compiled)
return;
g_assert (priv->program != COGL_INVALID_HANDLE);
if (priv->vertex_is_glsl && priv->vertex_shader != COGL_INVALID_HANDLE)
cogl_handle_unref (priv->vertex_shader);
if (priv->fragment_is_glsl && priv->fragment_shader != COGL_INVALID_HANDLE)
cogl_handle_unref (priv->fragment_shader);
if (priv->program != COGL_INVALID_HANDLE)
cogl_handle_unref (priv->program);
priv->vertex_shader = COGL_INVALID_HANDLE;
priv->fragment_shader = COGL_INVALID_HANDLE;
priv->program = COGL_INVALID_HANDLE;
priv->compiled = FALSE;
}
static void
clutter_shader_finalize (GObject *object)
{
@ -104,8 +129,6 @@ clutter_shader_finalize (GObject *object)
shader = CLUTTER_SHADER (object);
priv = shader->priv;
clutter_shader_release (shader);
clutter_shaders_list = g_list_remove (clutter_shaders_list, object);
g_free (priv->fragment_source);
@ -114,6 +137,16 @@ clutter_shader_finalize (GObject *object)
G_OBJECT_CLASS (clutter_shader_parent_class)->finalize (object);
}
static void
clutter_shader_dispose (GObject *object)
{
ClutterShader *shader = CLUTTER_SHADER (object);
clutter_shader_release_internal (shader);
G_OBJECT_CLASS (clutter_shader_parent_class)->finalize (object);
}
static void
clutter_shader_set_property (GObject *object,
guint prop_id,
@ -197,6 +230,7 @@ clutter_shader_class_init (ClutterShaderClass *klass)
GParamSpec *pspec = NULL;
object_class->finalize = clutter_shader_finalize;
object_class->dispose = clutter_shader_dispose;
object_class->set_property = clutter_shader_set_property;
object_class->get_property = clutter_shader_get_property;
object_class->constructor = clutter_shader_constructor;
@ -584,30 +618,9 @@ clutter_shader_compile (ClutterShader *shader,
void
clutter_shader_release (ClutterShader *shader)
{
ClutterShaderPrivate *priv;
g_return_if_fail (CLUTTER_IS_SHADER (shader));
priv = shader->priv;
if (!priv->compiled)
return;
g_assert (priv->program != COGL_INVALID_HANDLE);
if (priv->vertex_is_glsl && priv->vertex_shader != COGL_INVALID_HANDLE)
cogl_handle_unref (priv->vertex_shader);
if (priv->fragment_is_glsl && priv->fragment_shader != COGL_INVALID_HANDLE)
cogl_handle_unref (priv->fragment_shader);
if (priv->program != COGL_INVALID_HANDLE)
cogl_handle_unref (priv->program);
priv->vertex_shader = COGL_INVALID_HANDLE;
priv->fragment_shader = COGL_INVALID_HANDLE;
priv->program = COGL_INVALID_HANDLE;
priv->compiled = FALSE;
clutter_shader_release_internal (shader);
_clutter_notify_by_pspec (G_OBJECT (shader), obj_props[PROP_COMPILED]);
}