actor: visualize culling with CLUTTER_PAINT=redraws

This extends visualization for CLUTTER_PAINT=redraws so it now also
draws outlines for actors to show how they are being culled. Actors get
a green outline if they are fully inside the clip region, blue if fully
outside and greeny-blue if only partially inside.
This commit is contained in:
Robert Bragg 2011-03-15 12:08:46 +00:00
parent c739cb2809
commit 8557bc3d26
2 changed files with 121 additions and 48 deletions

View File

@ -2402,42 +2402,19 @@ _clutter_actor_apply_modelview_transform_recursive (ClutterActor *self,
} }
static void static void
_clutter_actor_draw_paint_volume (ClutterActor *self) _clutter_actor_draw_paint_volume_full (ClutterActor *self,
ClutterPaintVolume *pv,
const char *label,
const CoglColor *color)
{ {
static CoglMaterial *outline = NULL; static CoglMaterial *outline = NULL;
CoglHandle vbo; CoglHandle vbo;
ClutterPaintVolume *pv;
gboolean free_fake_pv;
ClutterPaintVolume fake_pv;
ClutterVertex line_ends[12 * 2]; ClutterVertex line_ends[12 * 2];
int n_vertices; int n_vertices;
PangoLayout *layout;
CoglColor color;
if (outline == NULL) if (outline == NULL)
outline = cogl_material_new (); outline = cogl_material_new ();
pv = _clutter_actor_get_paint_volume_mutable (self);
if (!pv)
{
gfloat width, height;
ClutterActor *stage = _clutter_actor_get_stage_internal (self);
_clutter_paint_volume_init_static (&fake_pv, stage);
free_fake_pv = TRUE;
clutter_actor_get_size (self, &width, &height);
clutter_paint_volume_set_width (&fake_pv, width);
clutter_paint_volume_set_height (&fake_pv, height);
pv = &fake_pv;
cogl_color_init_from_4f (&color, 0, 0, 1, 1);
}
else
{
cogl_color_init_from_4f (&color, 0, 1, 0, 1);
free_fake_pv = FALSE;
}
_clutter_paint_volume_complete (pv); _clutter_paint_volume_complete (pv);
n_vertices = pv->is_2d ? 4 * 2 : 12 * 2; n_vertices = pv->is_2d ? 4 * 2 : 12 * 2;
@ -2472,23 +2449,103 @@ _clutter_actor_draw_paint_volume (ClutterActor *self)
0, /* stride */ 0, /* stride */
line_ends); line_ends);
cogl_material_set_color (outline, &color); cogl_material_set_color (outline, color);
cogl_set_source (outline); cogl_set_source (outline);
cogl_vertex_buffer_draw (vbo, COGL_VERTICES_MODE_LINES, cogl_vertex_buffer_draw (vbo, COGL_VERTICES_MODE_LINES,
0 , n_vertices); 0 , n_vertices);
cogl_object_unref (vbo); cogl_object_unref (vbo);
layout = pango_layout_new (clutter_actor_get_pango_context (self)); if (label)
pango_layout_set_text (layout, G_OBJECT_TYPE_NAME (self), -1); {
cogl_pango_render_layout (layout, PangoLayout *layout;
pv->vertices[0].x, layout = pango_layout_new (clutter_actor_get_pango_context (self));
pv->vertices[0].y, pango_layout_set_text (layout, label, -1);
&color, cogl_pango_render_layout (layout,
0); pv->vertices[0].x,
g_object_unref (layout); pv->vertices[0].y,
color,
0);
g_object_unref (layout);
}
}
if (free_fake_pv) static void
clutter_paint_volume_free (&fake_pv); _clutter_actor_draw_paint_volume (ClutterActor *self)
{
ClutterPaintVolume *pv;
CoglColor color;
pv = _clutter_actor_get_paint_volume_mutable (self);
if (!pv)
{
gfloat width, height;
ClutterPaintVolume fake_pv;
ClutterActor *stage = _clutter_actor_get_stage_internal (self);
_clutter_paint_volume_init_static (&fake_pv, stage);
clutter_actor_get_size (self, &width, &height);
clutter_paint_volume_set_width (&fake_pv, width);
clutter_paint_volume_set_height (&fake_pv, height);
cogl_color_init_from_4f (&color, 0, 0, 1, 1);
_clutter_actor_draw_paint_volume_full (self, &fake_pv,
G_OBJECT_TYPE_NAME (self),
&color);
clutter_paint_volume_free (&fake_pv);
}
else
{
cogl_color_init_from_4f (&color, 0, 1, 0, 1);
_clutter_actor_draw_paint_volume_full (self, pv,
G_OBJECT_TYPE_NAME (self),
&color);
}
}
static void
_clutter_actor_paint_cull_result (ClutterActor *self,
gboolean success,
ClutterCullResult result)
{
ClutterPaintVolume *pv;
CoglColor color;
if (success)
{
if (result == CLUTTER_CULL_RESULT_IN)
cogl_color_init_from_4f (&color, 0, 1, 0, 1);
else if (result == CLUTTER_CULL_RESULT_OUT)
cogl_color_init_from_4f (&color, 0, 0, 1, 1);
else
cogl_color_init_from_4f (&color, 0, 1, 1, 1);
}
else
cogl_color_init_from_4f (&color, 1, 1, 1, 1);
if (success && (pv = _clutter_actor_get_paint_volume_mutable (self)))
_clutter_actor_draw_paint_volume_full (self, pv,
G_OBJECT_TYPE_NAME (self),
&color);
else
{
PangoLayout *layout;
char *label =
g_strdup_printf ("CULL FAILURE: %s", G_OBJECT_TYPE_NAME (self));
cogl_color_init_from_4f (&color, 1, 1, 1, 1);
cogl_set_source_color (&color);
layout = pango_layout_new (clutter_actor_get_pango_context (self));
pango_layout_set_text (layout, label, -1);
cogl_pango_render_layout (layout,
0,
0,
&color,
0);
g_free (label);
g_object_unref (layout);
}
} }
static int clone_paint_level = 0; static int clone_paint_level = 0;
@ -2517,12 +2574,11 @@ in_clone_paint (void)
* means there's no point in trying to cull descendants of the current * means there's no point in trying to cull descendants of the current
* node. */ * node. */
static gboolean static gboolean
cull_actor (ClutterActor *self) cull_actor (ClutterActor *self, ClutterCullResult *result_out)
{ {
ClutterActorPrivate *priv = self->priv; ClutterActorPrivate *priv = self->priv;
ClutterActor *stage; ClutterActor *stage;
const ClutterPlane *stage_clip; const ClutterPlane *stage_clip;
ClutterCullResult result;
if (!priv->last_paint_volume_valid) if (!priv->last_paint_volume_valid)
{ {
@ -2554,12 +2610,9 @@ cull_actor (ClutterActor *self)
return FALSE; return FALSE;
} }
result = _clutter_paint_volume_cull (&priv->last_paint_volume, stage_clip); *result_out =
if (result == CLUTTER_CULL_RESULT_IN || _clutter_paint_volume_cull (&priv->last_paint_volume, stage_clip);
result == CLUTTER_CULL_RESULT_PARTIAL) return TRUE;
return FALSE;
else
return TRUE;
} }
static void static void
@ -2718,6 +2771,11 @@ clutter_actor_paint (ClutterActor *self)
*/ */
if (!in_clone_paint ()) if (!in_clone_paint ())
{ {
gboolean success;
/* annoyingly gcc warns if uninitialized even though
* the initialization is redundant :-( */
ClutterCullResult result = CLUTTER_CULL_RESULT_IN;
if (G_LIKELY ((clutter_paint_debug_flags & if (G_LIKELY ((clutter_paint_debug_flags &
(CLUTTER_DEBUG_DISABLE_CULLING | (CLUTTER_DEBUG_DISABLE_CULLING |
CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS)) != CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS)) !=
@ -2725,7 +2783,11 @@ clutter_actor_paint (ClutterActor *self)
CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS))) CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS)))
_clutter_actor_update_last_paint_volume (self); _clutter_actor_update_last_paint_volume (self);
if (cull_actor (self)) success = cull_actor (self, &result);
if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_REDRAWS))
_clutter_actor_paint_cull_result (self, success, result);
else if (result == CLUTTER_CULL_RESULT_OUT && success)
goto done; goto done;
} }

View File

@ -442,7 +442,18 @@ clutter_stage_glx_redraw (ClutterStageWindow *stage_window)
else else
{ {
CLUTTER_NOTE (CLIPPING, "Unclipped stage paint\n"); CLUTTER_NOTE (CLIPPING, "Unclipped stage paint\n");
_clutter_stage_do_paint (stage_x11->wrapper, NULL);
/* If we are trying to debug redraw issues then we want to pass
* the bounding_redraw_clip so it can be visualized */
if (G_UNLIKELY (clutter_paint_debug_flags &
CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS) &&
may_use_clipped_redraw)
{
_clutter_stage_do_paint (stage_x11->wrapper,
&stage_glx->bounding_redraw_clip);
}
else
_clutter_stage_do_paint (stage_x11->wrapper, NULL);
} }
if (may_use_clipped_redraw && if (may_use_clipped_redraw &&