diff --git a/clutter/clutter/clutter-frame-clock.c b/clutter/clutter/clutter-frame-clock.c index 504e47bf5..9b3b10eba 100644 --- a/clutter/clutter/clutter-frame-clock.c +++ b/clutter/clutter/clutter-frame-clock.c @@ -678,6 +678,51 @@ clutter_frame_clock_record_flip_time (ClutterFrameClock *frame_clock, frame_clock->last_flip_time_us = flip_time_us; } +GString * +clutter_frame_clock_get_max_render_time_debug_info (ClutterFrameClock *frame_clock) +{ + int64_t max_dispatch_to_swap_us = 0; + int64_t max_swap_to_rendering_done_us = 0; + int64_t max_swap_to_flip_us = 0; + int i; + GString *string; + + string = g_string_new (NULL); + g_string_append_printf (string, "Max render time: %ld µs", + clutter_frame_clock_compute_max_render_time_us (frame_clock)); + + if (frame_clock->got_measurements_last_frame) + g_string_append_printf (string, " ="); + else + g_string_append_printf (string, " (no measurements last frame)"); + + for (i = 0; i < ESTIMATE_QUEUE_LENGTH; ++i) + { + max_dispatch_to_swap_us = + MAX (max_dispatch_to_swap_us, + frame_clock->dispatch_to_swap_us.values[i]); + max_swap_to_rendering_done_us = + MAX (max_swap_to_rendering_done_us, + frame_clock->swap_to_rendering_done_us.values[i]); + max_swap_to_flip_us = + MAX (max_swap_to_flip_us, + frame_clock->swap_to_flip_us.values[i]); + } + + g_string_append_printf (string, "\nVblank duration: %ld µs +", + frame_clock->vblank_duration_us); + g_string_append_printf (string, "\nDispatch to swap: %ld µs +", + max_dispatch_to_swap_us); + g_string_append_printf (string, "\nmax(Swap to rendering done: %ld µs,", + max_swap_to_rendering_done_us); + g_string_append_printf (string, "\nSwap to flip: %ld µs) +", + max_swap_to_flip_us); + g_string_append_printf (string, "\nConstant: %d µs", + clutter_max_render_time_constant_us); + + return string; +} + static GSourceFuncs frame_clock_source_funcs = { NULL, NULL, diff --git a/clutter/clutter/clutter-frame-clock.h b/clutter/clutter/clutter-frame-clock.h index c825ecad9..e71b54987 100644 --- a/clutter/clutter/clutter-frame-clock.h +++ b/clutter/clutter/clutter-frame-clock.h @@ -94,4 +94,6 @@ float clutter_frame_clock_get_refresh_rate (ClutterFrameClock *frame_clock); void clutter_frame_clock_record_flip_time (ClutterFrameClock *frame_clock, int64_t flip_time_us); +GString * clutter_frame_clock_get_max_render_time_debug_info (ClutterFrameClock *frame_clock); + #endif /* CLUTTER_FRAME_CLOCK_H */ diff --git a/clutter/clutter/clutter-main.c b/clutter/clutter/clutter-main.c index fa206b307..a800138ea 100644 --- a/clutter/clutter/clutter-main.c +++ b/clutter/clutter/clutter-main.c @@ -136,6 +136,7 @@ static const GDebugKey clutter_paint_debug_keys[] = { { "paint-deform-tiles", CLUTTER_DEBUG_PAINT_DEFORM_TILES }, { "damage-region", CLUTTER_DEBUG_PAINT_DAMAGE_REGION }, { "disable-dynamic-max-render-time", CLUTTER_DEBUG_DISABLE_DYNAMIC_MAX_RENDER_TIME }, + { "max-render-time", CLUTTER_DEBUG_PAINT_MAX_RENDER_TIME }, }; gboolean diff --git a/clutter/clutter/clutter-main.h b/clutter/clutter/clutter-main.h index a0ee83b3e..846a9d68d 100644 --- a/clutter/clutter/clutter-main.h +++ b/clutter/clutter/clutter-main.h @@ -73,6 +73,7 @@ typedef enum CLUTTER_DEBUG_PAINT_DEFORM_TILES = 1 << 7, CLUTTER_DEBUG_PAINT_DAMAGE_REGION = 1 << 8, CLUTTER_DEBUG_DISABLE_DYNAMIC_MAX_RENDER_TIME = 1 << 9, + CLUTTER_DEBUG_PAINT_MAX_RENDER_TIME = 1 << 10, } ClutterDrawDebugFlag; /** diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c index 8627c6a17..fc170107f 100644 --- a/clutter/clutter/clutter-stage.c +++ b/clutter/clutter/clutter-stage.c @@ -1312,6 +1312,51 @@ clutter_stage_real_paint_view (ClutterStage *stage, clutter_stage_do_paint_view (stage, view, redraw_clip); } +static void +clutter_stage_paint (ClutterActor *actor, + ClutterPaintContext *paint_context) +{ + ClutterStageView *view; + + CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->paint (actor, paint_context); + + view = clutter_paint_context_get_stage_view (paint_context); + if (view && + G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_MAX_RENDER_TIME)) + { + cairo_rectangle_int_t view_layout; + ClutterFrameClock *frame_clock; + g_autoptr (GString) string = NULL; + PangoLayout *layout; + PangoRectangle logical; + ClutterColor color; + g_autoptr (ClutterPaintNode) node = NULL; + ClutterActorBox box; + + clutter_stage_view_get_layout (view, &view_layout); + frame_clock = clutter_stage_view_get_frame_clock (view); + + string = clutter_frame_clock_get_max_render_time_debug_info (frame_clock); + + layout = clutter_actor_create_pango_layout (actor, string->str); + pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT); + pango_layout_get_pixel_extents (layout, NULL, &logical); + + clutter_color_init (&color, 255, 255, 255, 255); + node = clutter_text_node_new (layout, &color); + + box.x1 = view_layout.x; + box.y1 = view_layout.y + 30; + box.x2 = box.x1 + logical.width; + box.y2 = box.y1 + logical.height; + clutter_paint_node_add_rectangle (node, &box); + + clutter_paint_node_paint (node, paint_context); + + g_object_unref (layout); + } +} + static void clutter_stage_class_init (ClutterStageClass *klass) { @@ -1335,6 +1380,7 @@ clutter_stage_class_init (ClutterStageClass *klass) actor_class->hide_all = clutter_stage_hide_all; actor_class->queue_relayout = clutter_stage_real_queue_relayout; actor_class->apply_transform = clutter_stage_real_apply_transform; + actor_class->paint = clutter_stage_paint; klass->paint_view = clutter_stage_real_paint_view;