Commit 25329280 authored by Emmanuele Bassi's avatar Emmanuele Bassi

Drop the UProf dependency

Nobody has been compiling Clutter with profiling enabled in a long time.

UProf itself hasn't been updated in 5 years, and it still depends on
deprecated components like dbus-glib, with no port to GDBus in sight.

The profiling code was moderately useful in the past, but these days
it's probably better to profile Cogl than Clutter itself; timing
information can be extracted by the timestamp on each diagnostic message
that is now available by default in the CLUTTER_NOTE macro, and we can
add ad hoc counters where needed.
parent df15f04f
......@@ -60,14 +60,6 @@ GObject-Introspection is available from:
git://git.gnome.org/gobject-introspection
If you want support for profiling Clutter you will also need:
• UProf ≥ @UPROF_REQ_VERSION@
UProf is available from:
git://github.com/rib/UProf.git
RESOURCES
-------------------------------------------------------------------------------
......@@ -162,10 +154,6 @@ Clutter has additional command line options for the configure script:
Build Clutter with coverage report support, provided by gcov. This
feature only works with the GNU Compiler Suite and gcov installed.
--enable-profile=[no/yes]
Build Clutter with profiling instrumentation. Requires the GNU
C Compiler and the UProf library.
--disable-tests
Disable building the Clutter tests suite.
......
......@@ -40,10 +40,6 @@ If you are building the Introspection data you will also need:
* [GObject-Introspection](http://git.gnome.org/browse/gobject-introspection)
If you want support for profiling Clutter you will also need:
* [UProf](git://github.com/rib/UProf.git)
Resources
---------
......
......@@ -30,7 +30,6 @@ AM_CPPFLAGS = \
-I$(top_builddir)/clutter \
$(CLUTTER_DEPRECATED_CFLAGS) \
$(CLUTTER_DEBUG_CFLAGS) \
$(CLUTTER_PROFILE_CFLAGS) \
$(CLUTTER_HIDDEN_VISIBILITY_CFLAGS) \
$(NULL)
......@@ -240,7 +239,6 @@ source_h_priv = \
clutter-paint-node-private.h \
clutter-paint-volume-private.h \
clutter-private.h \
clutter-profile.h \
clutter-script-private.h \
clutter-settings-private.h \
clutter-stage-manager-private.h \
......@@ -253,7 +251,6 @@ source_c_priv = \
clutter-easing.c \
clutter-event-translator.c \
clutter-id-pool.c \
clutter-profile.c \
$(NULL)
# deprecated installed headers
......@@ -844,7 +841,7 @@ clutter_deprecated_HEADERS = $(deprecated_h)
lib_LTLIBRARIES += libclutter-@CLUTTER_API_VERSION@.la
libclutter_@CLUTTER_API_VERSION@_la_LIBADD = $(LIBM) $(CLUTTER_LIBS) $(CLUTTER_PROFILE_LIBS)
libclutter_@CLUTTER_API_VERSION@_la_LIBADD = $(LIBM) $(CLUTTER_LIBS)
libclutter_@CLUTTER_API_VERSION@_la_DEPENDENCIES = $(win32_resources)
libclutter_@CLUTTER_API_VERSION@_la_SOURCES = \
......
......@@ -627,7 +627,6 @@
#include "clutter-paint-node-private.h"
#include "clutter-paint-volume-private.h"
#include "clutter-private.h"
#include "clutter-profile.h"
#include "clutter-property-transition.h"
#include "clutter-scriptable.h"
#include "clutter-script-private.h"
......@@ -3676,16 +3675,6 @@ clutter_actor_paint (ClutterActor *self)
gboolean shader_applied = FALSE;
ClutterStage *stage;
CLUTTER_STATIC_COUNTER (actor_paint_counter,
"Actor real-paint counter",
"Increments each time any actor is painted",
0 /* no application private data */);
CLUTTER_STATIC_COUNTER (actor_pick_counter,
"Actor pick-paint counter",
"Increments each time any actor is painted "
"for picking",
0 /* no application private data */);
g_return_if_fail (CLUTTER_IS_ACTOR (self));
if (CLUTTER_ACTOR_IN_DESTRUCTION (self))
......@@ -3796,16 +3785,12 @@ clutter_actor_paint (ClutterActor *self)
if (pick_mode == CLUTTER_PICK_NONE)
{
CLUTTER_COUNTER_INC (_clutter_uprof_context, actor_paint_counter);
/* We check whether we need to add the flatten effect before
each paint so that we can avoid having a mechanism for
applications to notify when the value of the
has_overlaps virtual changes. */
add_or_remove_flatten_effect (self);
}
else
CLUTTER_COUNTER_INC (_clutter_uprof_context, actor_pick_counter);
/* We save the current paint volume so that the next time the
* actor queues a redraw we can constrain the redraw to just
......
......@@ -49,7 +49,6 @@
#include "clutter-event-private.h"
#include "clutter-marshal.h"
#include "clutter-private.h"
#include "clutter-profile.h"
#include "clutter-stage-manager-private.h"
#include "clutter-stage-private.h"
#include "clutter-stage-window.h"
......
......@@ -65,7 +65,6 @@
#include "clutter-main.h"
#include "clutter-master-clock.h"
#include "clutter-private.h"
#include "clutter-profile.h"
#include "clutter-settings-private.h"
#include "clutter-stage-manager.h"
#include "clutter-stage-private.h"
......@@ -128,9 +127,6 @@ guint clutter_debug_flags = 0;
guint clutter_paint_debug_flags = 0;
guint clutter_pick_debug_flags = 0;
/* profile flags */
guint clutter_profile_flags = 0;
const guint clutter_major_version = CLUTTER_MAJOR_VERSION;
const guint clutter_minor_version = CLUTTER_MINOR_VERSION;
const guint clutter_micro_version = CLUTTER_MICRO_VERSION;
......@@ -171,13 +167,6 @@ static const GDebugKey clutter_paint_debug_keys[] = {
{ "paint-deform-tiles", CLUTTER_DEBUG_PAINT_DEFORM_TILES },
};
#ifdef CLUTTER_ENABLE_PROFILE
static const GDebugKey clutter_profile_keys[] = {
{"picking-only", CLUTTER_PROFILE_PICKING_ONLY },
{"disable-report", CLUTTER_PROFILE_DISABLE_REPORT }
};
#endif /* CLUTTER_ENABLE_DEBUG */
static void
clutter_threads_impl_lock (void)
{
......@@ -787,28 +776,6 @@ clutter_main_level (void)
return clutter_main_loop_level;
}
#ifdef CLUTTER_ENABLE_PROFILE
static gint (*prev_poll) (GPollFD *ufds, guint nfsd, gint timeout_) = NULL;
static gint
timed_poll (GPollFD *ufds,
guint nfsd,
gint timeout_)
{
gint ret;
CLUTTER_STATIC_TIMER (poll_timer,
"Mainloop", /* parent */
"Mainloop Idle",
"The time spent idle in poll()",
0 /* no application private data */);
CLUTTER_TIMER_START (uprof_get_mainloop_context (), poll_timer);
ret = prev_poll (ufds, nfsd, timeout_);
CLUTTER_TIMER_STOP (uprof_get_mainloop_context (), poll_timer);
return ret;
}
#endif
/**
* clutter_main:
*
......@@ -826,14 +793,6 @@ clutter_main (void)
return;
}
#ifdef CLUTTER_ENABLE_PROFILE
if (!prev_poll)
{
prev_poll = g_main_context_get_poll_func (NULL);
g_main_context_set_poll_func (NULL, timed_poll);
}
#endif
clutter_main_loop_level++;
CLUTTER_NOTE (MISC, "Entering main loop level %d", clutter_main_loop_level);
......@@ -1361,32 +1320,6 @@ clutter_arg_no_debug_cb (const char *key,
}
#endif /* CLUTTER_ENABLE_DEBUG */
#ifdef CLUTTER_ENABLE_PROFILE
static gboolean
clutter_arg_profile_cb (const char *key,
const char *value,
gpointer user_data)
{
clutter_profile_flags |=
g_parse_debug_string (value,
clutter_profile_keys,
G_N_ELEMENTS (clutter_profile_keys));
return TRUE;
}
static gboolean
clutter_arg_no_profile_cb (const char *key,
const char *value,
gpointer user_data)
{
clutter_profile_flags &=
~g_parse_debug_string (value,
clutter_profile_keys,
G_N_ELEMENTS (clutter_profile_keys));
return TRUE;
}
#endif /* CLUTTER_ENABLE_PROFILE */
GQuark
clutter_init_error_quark (void)
{
......@@ -1399,14 +1332,6 @@ clutter_init_real (GError **error)
ClutterMainContext *ctx;
ClutterBackend *backend;
#ifdef CLUTTER_ENABLE_PROFILE
CLUTTER_STATIC_TIMER (mainloop_timer,
NULL, /* no parent */
"Mainloop",
"The time spent in the clutter mainloop",
0 /* no application private data */);
#endif
/* Note, creates backend if not already existing, though parse args will
* have likely created it
*/
......@@ -1453,27 +1378,6 @@ clutter_init_real (GError **error)
if (!_clutter_feature_init (error))
return CLUTTER_INIT_ERROR_BACKEND;
#ifdef CLUTTER_ENABLE_PROFILE
/* We need to be absolutely sure that uprof has been initialized
* before calling _clutter_uprof_init. uprof_init (NULL, NULL)
* will be a NOP if it has been initialized but it will also
* mean subsequent parsing of the UProf GOptionGroup will have no
* affect.
*
* Sadly GOptionGroup based library initialization is extremly
* fragile by design because GOptionGroups have no notion of
* dependencies and our post_parse_hook may be called before
* the cogl or uprof groups get parsed.
*/
uprof_init (NULL, NULL);
_clutter_uprof_init ();
CLUTTER_TIMER_START (uprof_get_mainloop_context (), mainloop_timer);
if (clutter_profile_flags & CLUTTER_PROFILE_PICKING_ONLY)
_clutter_profile_suspend ();
#endif
clutter_text_direction = clutter_get_text_direction ();
/* Initiate event collection */
......@@ -1511,12 +1415,6 @@ static GOptionEntry clutter_args[] = {
{ "clutter-no-debug", 0, 0, G_OPTION_ARG_CALLBACK, clutter_arg_no_debug_cb,
N_("Clutter debugging flags to unset"), "FLAGS" },
#endif /* CLUTTER_ENABLE_DEBUG */
#ifdef CLUTTER_ENABLE_PROFILE
{ "clutter-profile", 0, 0, G_OPTION_ARG_CALLBACK, clutter_arg_profile_cb,
N_("Clutter profiling flags to set"), "FLAGS" },
{ "clutter-no-profile", 0, 0, G_OPTION_ARG_CALLBACK, clutter_arg_no_profile_cb,
N_("Clutter profiling flags to unset"), "FLAGS" },
#endif /* CLUTTER_ENABLE_PROFILE */
{ "clutter-enable-accessibility", 0, 0, G_OPTION_ARG_NONE, &clutter_enable_accessibility,
N_("Enable accessibility"), NULL },
{ NULL, },
......@@ -1566,18 +1464,6 @@ pre_parse_hook (GOptionContext *context,
}
#endif /* CLUTTER_ENABLE_DEBUG */
#ifdef CLUTTER_ENABLE_PROFILE
env_string = g_getenv ("CLUTTER_PROFILE");
if (env_string != NULL)
{
clutter_profile_flags =
g_parse_debug_string (env_string,
clutter_profile_keys,
G_N_ELEMENTS (clutter_profile_keys));
env_string = NULL;
}
#endif /* CLUTTER_ENABLE_PROFILE */
env_string = g_getenv ("CLUTTER_PICK");
if (env_string != NULL)
{
......@@ -1831,14 +1717,6 @@ clutter_init_with_args (int *argc,
group = cogl_get_option_group ();
g_option_context_add_group (context, group);
/* Note: That due to the implementation details of glib's goption
* parsing; cogl and uprof will not actually have there arguments
* parsed before the post_parse_hook is called! */
#ifdef CLUTTER_ENABLE_PROFILE
group = uprof_get_option_group ();
g_option_context_add_group (context, group);
#endif
if (entries)
g_option_context_add_main_entries (context, entries, translation_domain);
......@@ -1872,9 +1750,6 @@ clutter_parse_args (int *argc,
{
GOptionContext *option_context;
GOptionGroup *clutter_group, *cogl_group;
#ifdef CLUTTER_ENABLE_PROFILE
GOptionGroup *uprof_group;
#endif
GError *internal_error = NULL;
gboolean ret = TRUE;
......@@ -1892,11 +1767,6 @@ clutter_parse_args (int *argc,
cogl_group = cogl_get_option_group ();
g_option_context_add_group (option_context, cogl_group);
#ifdef CLUTTER_ENABLE_PROFILE
uprof_group = uprof_get_option_group ();
g_option_context_add_group (option_context, uprof_group);
#endif
if (!g_option_context_parse (option_context, argc, argv, &internal_error))
{
g_propagate_error (error, internal_error);
......@@ -3850,11 +3720,6 @@ _clutter_debug_messagev (const char *format,
g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, fmt, var_args);
#ifdef CLUTTER_ENABLE_PROFILE
if (_clutter_uprof_context != NULL)
uprof_context_vtrace_message (_clutter_uprof_context, format, var_args);
#endif
g_free (fmt);
}
......
......@@ -37,7 +37,6 @@
#include "clutter-master-clock-default.h"
#include "clutter-debug.h"
#include "clutter-private.h"
#include "clutter-profile.h"
#include "clutter-stage-manager-private.h"
#include "clutter-stage-private.h"
......@@ -354,20 +353,10 @@ master_clock_process_events (ClutterMasterClockDefault *master_clock,
gint64 start = g_get_monotonic_time ();
#endif
CLUTTER_STATIC_TIMER (master_event_process,
"Master Clock",
"Event Processing",
"The time spent processing events on all stages",
0);
CLUTTER_TIMER_START (_clutter_uprof_context, master_event_process);
/* Process queued events */
for (l = stages; l != NULL; l = l->next)
_clutter_stage_process_queued_events (l->data);
CLUTTER_TIMER_STOP (_clutter_uprof_context, master_event_process);
#ifdef CLUTTER_ENABLE_DEBUG
if (_clutter_diagnostic_enabled ())
clutter_warn_if_over_budget (master_clock, start, "Event processing");
......@@ -392,12 +381,6 @@ master_clock_advance_timelines (ClutterMasterClockDefault *master_clock)
gint64 start = g_get_monotonic_time ();
#endif
CLUTTER_STATIC_TIMER (master_timeline_advance,
"Master Clock",
"Timelines Advancement",
"The time spent advancing all timelines",
0);
/* we protect ourselves from timelines being removed during
* the advancement by other timelines by copying the list of
* timelines, taking a reference on them, iterating over the
......@@ -421,13 +404,9 @@ master_clock_advance_timelines (ClutterMasterClockDefault *master_clock)
timelines = g_slist_copy (master_clock->timelines);
g_slist_foreach (timelines, (GFunc) g_object_ref, NULL);
CLUTTER_TIMER_START (_clutter_uprof_context, master_timeline_advance);
for (l = timelines; l != NULL; l = l->next)
_clutter_timeline_do_tick (l->data, master_clock->cur_tick / 1000);
CLUTTER_TIMER_STOP (_clutter_uprof_context, master_timeline_advance);
g_slist_foreach (timelines, (GFunc) g_object_unref, NULL);
g_slist_free (timelines);
......@@ -548,14 +527,6 @@ clutter_clock_dispatch (GSource *source,
gboolean stages_updated = FALSE;
GSList *stages;
CLUTTER_STATIC_TIMER (master_dispatch_timer,
"Mainloop",
"Master Clock",
"Master clock dispatch",
0);
CLUTTER_TIMER_START (_clutter_uprof_context, master_dispatch_timer);
CLUTTER_NOTE (SCHEDULER, "Master clock [tick]");
_clutter_threads_acquire_lock ();
......@@ -603,8 +574,6 @@ clutter_clock_dispatch (GSource *source,
_clutter_threads_release_lock ();
CLUTTER_TIMER_STOP (_clutter_uprof_context, master_dispatch_timer);
return TRUE;
}
......
#ifdef CLUTTER_ENABLE_PROFILE
#include <stdlib.h>
/* XXX - we need this for g_atexit() */
#define G_DISABLE_DEPRECATION_WARNINGS
#include "clutter-profile.h"
UProfContext *_clutter_uprof_context;
static UProfReport *clutter_uprof_report;
static gboolean searched_for_gl_uprof_context = FALSE;
static UProfContext *gl_uprof_context = NULL;
typedef struct _ClutterUProfReportState
{
gulong n_frames;
float fps;
gulong n_picks;
float msecs_picking;
} ClutterUProfReportState;
static char *
timer_per_frame_cb (UProfReport *report,
UProfTimerResult *timer,
void *user_data)
{
ClutterUProfReportState *state = user_data;
int n_frames = state->n_frames ? state->n_frames : 1;
return g_strdup_printf ("%-10.2f",
uprof_timer_result_get_total_msecs (timer) /
(float)n_frames);
}
static char *
counter_per_frame_cb (UProfReport *report,
UProfCounterResult *counter,
void *user_data)
{
ClutterUProfReportState *state = user_data;
int n_frames = state->n_frames ? state->n_frames : 1;
return g_strdup_printf ("%-5ld",
uprof_counter_result_get_count (counter) /
n_frames);
}
static char *
get_n_frames_cb (UProfReport *report,
const char *statistic,
const char *attribute,
void *user_data)
{
ClutterUProfReportState *state = user_data;
return g_strdup_printf ("%lu", state->n_frames);
}
static char *
get_fps_cb (UProfReport *report,
const char *statistic,
const char *attribute,
void *user_data)
{
ClutterUProfReportState *state = user_data;
return g_strdup_printf ("%5.2f\n", state->fps);
}
static char *
get_n_picks_cb (UProfReport *report,
const char *statistic,
const char *attribute,
void *user_data)
{
ClutterUProfReportState *state = user_data;
return g_strdup_printf ("%lu", state->n_picks);
}
static char *
get_picks_per_frame_cb (UProfReport *report,
const char *statistic,
const char *attribute,
void *user_data)
{
ClutterUProfReportState *state = user_data;
int n_frames = state->n_frames ? state->n_frames : 1;
return g_strdup_printf ("%3.2f",
(float)state->n_picks / (float)n_frames);
}
static char *
get_msecs_per_pick_cb (UProfReport *report,
const char *statistic,
const char *attribute,
void *user_data)
{
ClutterUProfReportState *state = user_data;
int n_picks = state->n_picks ? state->n_picks : 1;
return g_strdup_printf ("%3.2f", state->msecs_picking / (float)n_picks);
}
static gboolean
_clutter_uprof_report_prepare (UProfReport *report,
void **closure_ret,
void *user_data)
{
UProfContext *mainloop_context;
UProfTimerResult *mainloop_timer;
UProfTimerResult *stage_paint_timer;
UProfTimerResult *do_pick_timer;
ClutterUProfReportState *state;
/* NB: uprof provides a shared context for mainloop statistics which allows
* this to work even if the application and not Clutter owns the mainloop.
*
* This is the case when running Mutter for example but because Mutter will
* follow the same convention of using the shared context then we can always
* be sure of where to look for the mainloop results. */
mainloop_context = uprof_get_mainloop_context ();
mainloop_timer = uprof_context_get_timer_result (mainloop_context,
"Mainloop");
/* just bail out if the mainloop timer wasn't hit */
if (!mainloop_timer)
return FALSE;
state = g_new0 (ClutterUProfReportState, 1);
*closure_ret = state;
stage_paint_timer = uprof_context_get_timer_result (_clutter_uprof_context,
"Redrawing");
if (stage_paint_timer)
{
state->n_frames = uprof_timer_result_get_start_count (stage_paint_timer);
uprof_report_add_statistic (report,
"Frames",
"Frame count information");
uprof_report_add_statistic_attribute (report, "Frames",
"Count", "Count",
"The total number of frames",
UPROF_ATTRIBUTE_TYPE_INT,
get_n_frames_cb,
state);
state->fps = (float) state->n_frames
/ (uprof_timer_result_get_total_msecs (mainloop_timer)
/ 1000.0);
uprof_report_add_statistic_attribute (report, "Frames",
"Average FPS", "Average\nFPS",
"The average frames per second",
UPROF_ATTRIBUTE_TYPE_FLOAT,
get_fps_cb,
state);
}
do_pick_timer = uprof_context_get_timer_result (_clutter_uprof_context,
"Picking");
if (do_pick_timer)
{
state->n_picks = uprof_timer_result_get_start_count (do_pick_timer);
state->msecs_picking =
uprof_timer_result_get_total_msecs (do_pick_timer);
uprof_report_add_statistic (report,
"Picks",
"Picking information");
uprof_report_add_statistic_attribute (report, "Picks",
"Count", "Count",
"The total number of picks",
UPROF_ATTRIBUTE_TYPE_INT,
get_n_picks_cb,
state);
uprof_report_add_statistic_attribute (report, "Picks",
"Picks Per Frame",
"Picks\nPer Frame",
"The average number of picks "
"per frame",
UPROF_ATTRIBUTE_TYPE_FLOAT,
get_picks_per_frame_cb,
state);
uprof_report_add_statistic_attribute (report, "Picks",
"Msecs Per Pick",
"Msecs\nPer Pick",
"The average number of "
"milliseconds per pick",
UPROF_ATTRIBUTE_TYPE_FLOAT,
get_msecs_per_pick_cb,
state);
}
uprof_report_add_counters_attribute (clutter_uprof_report,
"Per Frame",
"Per Frame",
"The number of counts per frame",
UPROF_ATTRIBUTE_TYPE_INT,
counter_per_frame_cb,
state);
uprof_report_add_timers_attribute (clutter_uprof_report,
"Per Frame\nmsecs",
"Per Frame",
"The time spent in the timer per frame",
UPROF_ATTRIBUTE_TYPE_FLOAT,
timer_per_frame_cb,
state);
return TRUE;
}
static void
_clutter_uprof_report_done (UProfReport *report, void *closure, void *user_data)
{
g_free (closure);
}
static void
print_exit_report (void)
{
if (!(clutter_profile_flags & CLUTTER_PROFILE_DISABLE_REPORT))
uprof_report_print (clutter_uprof_report);
uprof_report_unref (clutter_uprof_report);
uprof_context_unref (_clutter_uprof_context);
}
void
_clutter_uprof_init (void)
{
UProfContext *cogl_context;
_clutter_uprof_context = uprof_context_new ("Clutter");
uprof_context_link (_clutter_uprof_context, uprof_get_mainloop_context ());
g_atexit (print_exit_report);
cogl_context = uprof_find_context ("Cogl");
if (cogl_context)
uprof_context_link (_clutter_uprof_context, cogl_context);
/* We make the report object up-front so we can use uprof-tool
* to fetch reports at runtime via dbus... */
clutter_uprof_report = uprof_report_new ("Clutter report");
uprof_report_add_context (clutter_uprof_report, _clutter_uprof_context);
uprof_report_set_init_fini_callbacks (clutter_uprof_report,
_clutter_uprof_report_prepare,
_clutter_uprof_report_done,
NULL);
}
void
_clutter_profile_suspend (void)
{
if (G_UNLIKELY (!searched_for_gl_uprof_context))
{
gl_uprof_context = uprof_find_context ("OpenGL");
searched_for_gl_uprof_context = TRUE;
}
if (gl_uprof_context)
uprof_context_suspend (gl_uprof_context);
/* NB: The Cogl context is linked to this so it will also be suspended... */
uprof_context_suspend (_clutter_uprof_context);
}
void
_clutter_profile_resume (void)
{
if (gl_uprof_context)
uprof_context_resume (gl_uprof_context);
/* NB: The Cogl context is linked to this so it will also be resumed... */
uprof_context_resume (_clutter_uprof_context);
}
#endif
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright (C) 2009 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CLUTTER_PROFILE_H__
#define __CLUTTER_PROFILE_H__
#include <glib.h>
G_BEGIN_DECLS
typedef enum {
CLUTTER_PROFILE_PICKING_ONLY = 1 << 0,
CLUTTER_PROFILE_DISABLE_REPORT = 1 << 1
} ClutterProfileFlag;
#ifdef CLUTTER_ENABLE_PROFILE
#include <uprof.h>
extern UProfContext * _clutter_uprof_context;
extern guint clutter_profile_flags;
#define CLUTTER_STATIC_TIMER UPROF_STATIC_TIMER
#define CLUTTER_STATIC_COUNTER UPROF_STATIC_COUNTER
#define CLUTTER_COUNTER_INC UPROF_COUNTER_INC
#define CLUTTER_COUNTER_DEC UPROF_COUNTER_DEC
#define CLUTTER_TIMER_START UPROF_TIMER_START
#define CLUTTER_TIMER_STOP UPROF_TIMER_STOP