From 72eeb8e809492524dc146cb92e0b4e3a5347f628 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Wed, 8 Sep 2010 19:47:11 +0100 Subject: [PATCH] actor: make default get_paint_volume more conservative There are too many examples where the default assumption that an actor paints inside its allocation isn't true, so we now return FALSE in the base implementation instead. This means that by default we are saying "we don't know the paint volume of the actor", so developers need to implement the get_paint_volume virtual to take advantage of culling and clipped redraws with their actors. This patch provides very conservative get_paint_volume implementations for ClutterTexture, ClutterCairoTexture, ClutterRectangle and ClutterText which all explicitly check the actor's object type to avoid making any assumptions about subclasses. --- clutter/clutter-actor.c | 14 +------------- clutter/clutter-cairo-texture.c | 28 +++++++++++++++++++++++++++ clutter/clutter-rectangle.c | 28 ++++++++++++++++++++++++++- clutter/clutter-text.c | 26 +++++++++++++++++++++++++ clutter/clutter-texture.c | 34 +++++++++++++++++++++++++++++---- 5 files changed, 112 insertions(+), 18 deletions(-) diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index c3cfeefa6..2b37b4bea 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -3457,19 +3457,7 @@ static gboolean clutter_actor_real_get_paint_volume (ClutterActor *self, ClutterPaintVolume *volume) { - ClutterActorPrivate *priv = self->priv; - gfloat width, height; - - if (G_UNLIKELY (priv->needs_allocation)) - return FALSE; - - /* the default origin is set to { 0, 0, 0 } */ - clutter_actor_box_get_size (&priv->allocation, &width, &height); - clutter_paint_volume_set_width (volume, width); - clutter_paint_volume_set_height (volume, height); - /* the default depth will be 0 since most actors are 2D */ - - return TRUE; + return FALSE; } static void diff --git a/clutter/clutter-cairo-texture.c b/clutter/clutter-cairo-texture.c index 41fdbbaa6..849e3f3f5 100644 --- a/clutter/clutter-cairo-texture.c +++ b/clutter/clutter-cairo-texture.c @@ -366,6 +366,31 @@ clutter_cairo_texture_get_preferred_height (ClutterActor *actor, *natural_height = (gfloat) priv->height; } +static gboolean +clutter_cairo_texture_get_paint_volume (ClutterActor *self, + ClutterPaintVolume *volume) +{ + ClutterGeometry allocation; + + /* XXX: we are being conservative here and not making assumptions + * that sub-classes won't paint outside their allocation. */ + if (G_OBJECT_TYPE (self) != CLUTTER_TYPE_CAIRO_TEXTURE) + return FALSE; + + /* XXX: clutter_actor_get_allocation can potentially be very + * expensive to call if called while the actor doesn't have a valid + * allocation since it will trigger a synchronous relayout of the + * scenegraph. We explicitly check we have a valid allocation + * to avoid hitting that codepath. */ + if (!clutter_actor_has_allocation (self)) + return FALSE; + + clutter_actor_get_allocation_geometry (self, &allocation); + clutter_paint_volume_set_width (volume, allocation.width); + clutter_paint_volume_set_height (volume, allocation.height); + return TRUE; +} + static void clutter_cairo_texture_class_init (ClutterCairoTextureClass *klass) { @@ -378,6 +403,9 @@ clutter_cairo_texture_class_init (ClutterCairoTextureClass *klass) gobject_class->get_property = clutter_cairo_texture_get_property; gobject_class->notify = clutter_cairo_texture_notify; + actor_class->get_paint_volume = + clutter_cairo_texture_get_paint_volume; + actor_class->get_preferred_width = clutter_cairo_texture_get_preferred_width; actor_class->get_preferred_height = diff --git a/clutter/clutter-rectangle.c b/clutter/clutter-rectangle.c index 763193afe..c0fd30a6d 100644 --- a/clutter/clutter-rectangle.c +++ b/clutter/clutter-rectangle.c @@ -152,6 +152,31 @@ clutter_rectangle_paint (ClutterActor *self) } } +static gboolean +clutter_rectangle_get_paint_volume (ClutterActor *self, + ClutterPaintVolume *volume) +{ + ClutterGeometry allocation; + + /* XXX: we are being conservative here and not making assumptions + * that sub-classes won't paint outside their allocation. */ + if (G_OBJECT_TYPE (self) != CLUTTER_TYPE_RECTANGLE) + return FALSE; + + /* XXX: clutter_actor_get_allocation can potentially be very + * expensive to call if called while the actor doesn't have a valid + * allocation since it will trigger a synchronous relayout of the + * scenegraph. We explicitly check we have a valid allocation + * to avoid hitting that codepath. */ + if (!clutter_actor_has_allocation (self)) + return FALSE; + + clutter_actor_get_allocation_geometry (self, &allocation); + clutter_paint_volume_set_width (volume, allocation.width); + clutter_paint_volume_set_height (volume, allocation.height); + return TRUE; +} + static void clutter_rectangle_set_property (GObject *object, guint prop_id, @@ -231,7 +256,8 @@ clutter_rectangle_class_init (ClutterRectangleClass *klass) ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); GParamSpec *pspec; - actor_class->paint = clutter_rectangle_paint; + actor_class->paint = clutter_rectangle_paint; + actor_class->get_paint_volume = clutter_rectangle_get_paint_volume; gobject_class->finalize = clutter_rectangle_finalize; gobject_class->dispose = clutter_rectangle_dispose; diff --git a/clutter/clutter-text.c b/clutter/clutter-text.c index 3bf729d76..3c32c9fd3 100644 --- a/clutter/clutter-text.c +++ b/clutter/clutter-text.c @@ -1920,6 +1920,31 @@ clutter_text_paint (ClutterActor *self) } +static gboolean +clutter_text_get_paint_volume (ClutterActor *self, + ClutterPaintVolume *volume) +{ + ClutterGeometry allocation; + + /* XXX: we are being conservative here and not making assumptions + * that sub-classes won't paint outside their allocation. */ + if (G_OBJECT_TYPE (self) != CLUTTER_TYPE_TEXT) + return FALSE; + + /* XXX: clutter_actor_get_allocation can potentially be very + * expensive to call if called while the actor doesn't have a valid + * allocation since it will trigger a synchronous relayout of the + * scenegraph. We explicitly check we have a valid allocation + * to avoid hitting that codepath. */ + if (!clutter_actor_has_allocation (self)) + return FALSE; + + clutter_actor_get_allocation_geometry (self, &allocation); + clutter_paint_volume_set_width (volume, allocation.width); + clutter_paint_volume_set_height (volume, allocation.height); + return TRUE; +} + static void clutter_text_get_preferred_width (ClutterActor *self, gfloat for_height, @@ -2492,6 +2517,7 @@ clutter_text_class_init (ClutterTextClass *klass) gobject_class->finalize = clutter_text_finalize; actor_class->paint = clutter_text_paint; + actor_class->get_paint_volume = clutter_text_get_paint_volume; actor_class->get_preferred_width = clutter_text_get_preferred_width; actor_class->get_preferred_height = clutter_text_get_preferred_height; actor_class->allocate = clutter_text_allocate; diff --git a/clutter/clutter-texture.c b/clutter/clutter-texture.c index ee342ca7c..0630fb872 100644 --- a/clutter/clutter-texture.c +++ b/clutter/clutter-texture.c @@ -685,6 +685,31 @@ clutter_texture_paint (ClutterActor *self) gen_texcoords_and_draw_cogl_rectangle (self); } +static gboolean +clutter_texture_get_paint_volume (ClutterActor *self, + ClutterPaintVolume *volume) +{ + ClutterGeometry allocation; + + /* XXX: we are being conservative here and not making assumptions + * that sub-classes won't paint outside their allocation. */ + if (G_OBJECT_TYPE (self) != CLUTTER_TYPE_TEXTURE) + return FALSE; + + /* XXX: clutter_actor_get_allocation can potentially be very + * expensive to call if called while the actor doesn't have a valid + * allocation since it will trigger a synchronous relayout of the + * scenegraph. We explicitly check we have a valid allocation + * to avoid hitting that codepath. */ + if (!clutter_actor_has_allocation (self)) + return FALSE; + + clutter_actor_get_allocation_geometry (self, &allocation); + clutter_paint_volume_set_width (volume, allocation.width); + clutter_paint_volume_set_height (volume, allocation.height); + return TRUE; +} + static void clutter_texture_async_data_free (ClutterTextureAsyncData *data) { @@ -956,10 +981,11 @@ clutter_texture_class_init (ClutterTextureClass *klass) g_type_class_add_private (klass, sizeof (ClutterTexturePrivate)); - actor_class->paint = clutter_texture_paint; - actor_class->pick = clutter_texture_pick; - actor_class->realize = clutter_texture_realize; - actor_class->unrealize = clutter_texture_unrealize; + actor_class->paint = clutter_texture_paint; + actor_class->pick = clutter_texture_pick; + actor_class->get_paint_volume = clutter_texture_get_paint_volume; + actor_class->realize = clutter_texture_realize; + actor_class->unrealize = clutter_texture_unrealize; actor_class->get_preferred_width = clutter_texture_get_preferred_width; actor_class->get_preferred_height = clutter_texture_get_preferred_height;