shader: Don't notify properties when finalizing shaders
authorDamien Lespiau <damien.lespiau@intel.com>
Tue, 11 Jan 2011 10:23:59 +0000 (10:23 +0000)
committerEmmanuele Bassi <ebassi@linux.intel.com>
Tue, 11 Jan 2011 11:20:16 +0000 (11:20 +0000)
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

clutter/clutter-shader.c

index c4cfd67..e2109c7 100644 (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);
@@ -115,6 +138,16 @@ clutter_shader_finalize (GObject *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,
                              const GValue *value,
@@ -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]);
 }