diff options
Diffstat (limited to 'tools/perf/ui/gtk')
| -rw-r--r-- | tools/perf/ui/gtk/annotate.c | 229 | ||||
| -rw-r--r-- | tools/perf/ui/gtk/browser.c | 237 | ||||
| -rw-r--r-- | tools/perf/ui/gtk/gtk.h | 11 | ||||
| -rw-r--r-- | tools/perf/ui/gtk/helpline.c | 23 | ||||
| -rw-r--r-- | tools/perf/ui/gtk/hists.c | 312 | ||||
| -rw-r--r-- | tools/perf/ui/gtk/progress.c | 59 | ||||
| -rw-r--r-- | tools/perf/ui/gtk/setup.c | 2 | ||||
| -rw-r--r-- | tools/perf/ui/gtk/util.c | 11 | 
8 files changed, 629 insertions, 255 deletions
diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c new file mode 100644 index 00000000000..7d8dc581a54 --- /dev/null +++ b/tools/perf/ui/gtk/annotate.c @@ -0,0 +1,229 @@ +#include "gtk.h" +#include "util/debug.h" +#include "util/annotate.h" +#include "ui/helpline.h" + + +enum { +	ANN_COL__PERCENT, +	ANN_COL__OFFSET, +	ANN_COL__LINE, + +	MAX_ANN_COLS +}; + +static const char *const col_names[] = { +	"Overhead", +	"Offset", +	"Line" +}; + +static int perf_gtk__get_percent(char *buf, size_t size, struct symbol *sym, +				 struct disasm_line *dl, int evidx) +{ +	struct sym_hist *symhist; +	double percent = 0.0; +	const char *markup; +	int ret = 0; + +	strcpy(buf, ""); + +	if (dl->offset == (s64) -1) +		return 0; + +	symhist = annotation__histogram(symbol__annotation(sym), evidx); +	if (!symhist->addr[dl->offset]) +		return 0; + +	percent = 100.0 * symhist->addr[dl->offset] / symhist->sum; + +	markup = perf_gtk__get_percent_color(percent); +	if (markup) +		ret += scnprintf(buf, size, "%s", markup); +	ret += scnprintf(buf + ret, size - ret, "%6.2f%%", percent); +	if (markup) +		ret += scnprintf(buf + ret, size - ret, "</span>"); + +	return ret; +} + +static int perf_gtk__get_offset(char *buf, size_t size, struct symbol *sym, +				struct map *map, struct disasm_line *dl) +{ +	u64 start = map__rip_2objdump(map, sym->start); + +	strcpy(buf, ""); + +	if (dl->offset == (s64) -1) +		return 0; + +	return scnprintf(buf, size, "%"PRIx64, start + dl->offset); +} + +static int perf_gtk__get_line(char *buf, size_t size, struct disasm_line *dl) +{ +	int ret = 0; +	char *line = g_markup_escape_text(dl->line, -1); +	const char *markup = "<span fgcolor='gray'>"; + +	strcpy(buf, ""); + +	if (!line) +		return 0; + +	if (dl->offset != (s64) -1) +		markup = NULL; + +	if (markup) +		ret += scnprintf(buf, size, "%s", markup); +	ret += scnprintf(buf + ret, size - ret, "%s", line); +	if (markup) +		ret += scnprintf(buf + ret, size - ret, "</span>"); + +	g_free(line); +	return ret; +} + +static int perf_gtk__annotate_symbol(GtkWidget *window, struct symbol *sym, +				struct map *map, int evidx, +				struct hist_browser_timer *hbt __maybe_unused) +{ +	struct disasm_line *pos, *n; +	struct annotation *notes; +	GType col_types[MAX_ANN_COLS]; +	GtkCellRenderer *renderer; +	GtkListStore *store; +	GtkWidget *view; +	int i; +	char s[512]; + +	notes = symbol__annotation(sym); + +	for (i = 0; i < MAX_ANN_COLS; i++) { +		col_types[i] = G_TYPE_STRING; +	} +	store = gtk_list_store_newv(MAX_ANN_COLS, col_types); + +	view = gtk_tree_view_new(); +	renderer = gtk_cell_renderer_text_new(); + +	for (i = 0; i < MAX_ANN_COLS; i++) { +		gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), +					-1, col_names[i], renderer, "markup", +					i, NULL); +	} + +	gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store)); +	g_object_unref(GTK_TREE_MODEL(store)); + +	list_for_each_entry(pos, ¬es->src->source, node) { +		GtkTreeIter iter; + +		gtk_list_store_append(store, &iter); + +		if (perf_gtk__get_percent(s, sizeof(s), sym, pos, evidx)) +			gtk_list_store_set(store, &iter, ANN_COL__PERCENT, s, -1); +		if (perf_gtk__get_offset(s, sizeof(s), sym, map, pos)) +			gtk_list_store_set(store, &iter, ANN_COL__OFFSET, s, -1); +		if (perf_gtk__get_line(s, sizeof(s), pos)) +			gtk_list_store_set(store, &iter, ANN_COL__LINE, s, -1); +	} + +	gtk_container_add(GTK_CONTAINER(window), view); + +	list_for_each_entry_safe(pos, n, ¬es->src->source, node) { +		list_del(&pos->node); +		disasm_line__free(pos); +	} + +	return 0; +} + +int symbol__gtk_annotate(struct symbol *sym, struct map *map, int evidx, +			 struct hist_browser_timer *hbt) +{ +	GtkWidget *window; +	GtkWidget *notebook; +	GtkWidget *scrolled_window; +	GtkWidget *tab_label; + +	if (map->dso->annotate_warned) +		return -1; + +	if (symbol__annotate(sym, map, 0) < 0) { +		ui__error("%s", ui_helpline__current); +		return -1; +	} + +	if (perf_gtk__is_active_context(pgctx)) { +		window = pgctx->main_window; +		notebook = pgctx->notebook; +	} else { +		GtkWidget *vbox; +		GtkWidget *infobar; +		GtkWidget *statbar; + +		signal(SIGSEGV, perf_gtk__signal); +		signal(SIGFPE,  perf_gtk__signal); +		signal(SIGINT,  perf_gtk__signal); +		signal(SIGQUIT, perf_gtk__signal); +		signal(SIGTERM, perf_gtk__signal); + +		window = gtk_window_new(GTK_WINDOW_TOPLEVEL); +		gtk_window_set_title(GTK_WINDOW(window), "perf annotate"); + +		g_signal_connect(window, "delete_event", gtk_main_quit, NULL); + +		pgctx = perf_gtk__activate_context(window); +		if (!pgctx) +			return -1; + +		vbox = gtk_vbox_new(FALSE, 0); +		notebook = gtk_notebook_new(); +		pgctx->notebook = notebook; + +		gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0); + +		infobar = perf_gtk__setup_info_bar(); +		if (infobar) { +			gtk_box_pack_start(GTK_BOX(vbox), infobar, +					   FALSE, FALSE, 0); +		} + +		statbar = perf_gtk__setup_statusbar(); +		gtk_box_pack_start(GTK_BOX(vbox), statbar, FALSE, FALSE, 0); + +		gtk_container_add(GTK_CONTAINER(window), vbox); +	} + +	scrolled_window = gtk_scrolled_window_new(NULL, NULL); +	tab_label = gtk_label_new(sym->name); + +	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), +				       GTK_POLICY_AUTOMATIC, +				       GTK_POLICY_AUTOMATIC); + +	gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled_window, +				 tab_label); + +	perf_gtk__annotate_symbol(scrolled_window, sym, map, evidx, hbt); +	return 0; +} + +void perf_gtk__show_annotations(void) +{ +	GtkWidget *window; + +	if (!perf_gtk__is_active_context(pgctx)) +		return; + +	window = pgctx->main_window; +	gtk_widget_show_all(window); + +	perf_gtk__resize_window(window); +	gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); + +	gtk_main(); + +	perf_gtk__deactivate_context(&pgctx); +} diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c index 4125c628411..c95012cdb43 100644 --- a/tools/perf/ui/gtk/browser.c +++ b/tools/perf/ui/gtk/browser.c @@ -8,15 +8,13 @@  #include <signal.h> -#define MAX_COLUMNS			32 - -static void perf_gtk__signal(int sig) +void perf_gtk__signal(int sig)  {  	perf_gtk__exit(false);  	psignal(sig, "perf");  } -static void perf_gtk__resize_window(GtkWidget *window) +void perf_gtk__resize_window(GtkWidget *window)  {  	GdkRectangle rect;  	GdkScreen *screen; @@ -36,7 +34,7 @@ static void perf_gtk__resize_window(GtkWidget *window)  	gtk_window_resize(GTK_WINDOW(window), width, height);  } -static const char *perf_gtk__get_percent_color(double percent) +const char *perf_gtk__get_percent_color(double percent)  {  	if (percent >= MIN_RED)  		return "<span fgcolor='red'>"; @@ -45,155 +43,8 @@ static const char *perf_gtk__get_percent_color(double percent)  	return NULL;  } -#define HPP__COLOR_FN(_name, _field)						\ -static int perf_gtk__hpp_color_ ## _name(struct perf_hpp *hpp,			\ -					 struct hist_entry *he)			\ -{										\ -	struct hists *hists = he->hists;					\ -	double percent = 100.0 * he->stat._field / hists->stats.total_period;	\ -	const char *markup;							\ -	int ret = 0;								\ -										\ -	markup = perf_gtk__get_percent_color(percent);				\ -	if (markup)								\ -		ret += scnprintf(hpp->buf, hpp->size, "%s", markup);		\ -	ret += scnprintf(hpp->buf + ret, hpp->size - ret, "%6.2f%%", percent); 	\ -	if (markup)								\ -		ret += scnprintf(hpp->buf + ret, hpp->size - ret, "</span>"); 	\ -										\ -	return ret;								\ -} - -HPP__COLOR_FN(overhead, period) -HPP__COLOR_FN(overhead_sys, period_sys) -HPP__COLOR_FN(overhead_us, period_us) -HPP__COLOR_FN(overhead_guest_sys, period_guest_sys) -HPP__COLOR_FN(overhead_guest_us, period_guest_us) - -#undef HPP__COLOR_FN - -void perf_gtk__init_hpp(void) -{ -	perf_hpp__init(); - -	perf_hpp__format[PERF_HPP__OVERHEAD].color = -				perf_gtk__hpp_color_overhead; -	perf_hpp__format[PERF_HPP__OVERHEAD_SYS].color = -				perf_gtk__hpp_color_overhead_sys; -	perf_hpp__format[PERF_HPP__OVERHEAD_US].color = -				perf_gtk__hpp_color_overhead_us; -	perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].color = -				perf_gtk__hpp_color_overhead_guest_sys; -	perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].color = -				perf_gtk__hpp_color_overhead_guest_us; -} - -static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) -{ -	GType col_types[MAX_COLUMNS]; -	GtkCellRenderer *renderer; -	struct sort_entry *se; -	GtkListStore *store; -	struct rb_node *nd; -	GtkWidget *view; -	int i, col_idx; -	int nr_cols; -	char s[512]; - -	struct perf_hpp hpp = { -		.buf		= s, -		.size		= sizeof(s), -	}; - -	nr_cols = 0; - -	for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { -		if (!perf_hpp__format[i].cond) -			continue; - -		col_types[nr_cols++] = G_TYPE_STRING; -	} - -	list_for_each_entry(se, &hist_entry__sort_list, list) { -		if (se->elide) -			continue; - -		col_types[nr_cols++] = G_TYPE_STRING; -	} - -	store = gtk_list_store_newv(nr_cols, col_types); - -	view = gtk_tree_view_new(); - -	renderer = gtk_cell_renderer_text_new(); - -	col_idx = 0; - -	for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { -		if (!perf_hpp__format[i].cond) -			continue; - -		perf_hpp__format[i].header(&hpp); - -		gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), -							    -1, s, -							    renderer, "markup", -							    col_idx++, NULL); -	} - -	list_for_each_entry(se, &hist_entry__sort_list, list) { -		if (se->elide) -			continue; - -		gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), -							    -1, se->se_header, -							    renderer, "text", -							    col_idx++, NULL); -	} - -	gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store)); - -	g_object_unref(GTK_TREE_MODEL(store)); - -	for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { -		struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); -		GtkTreeIter iter; - -		if (h->filtered) -			continue; - -		gtk_list_store_append(store, &iter); - -		col_idx = 0; - -		for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { -			if (!perf_hpp__format[i].cond) -				continue; - -			if (perf_hpp__format[i].color) -				perf_hpp__format[i].color(&hpp, h); -			else -				perf_hpp__format[i].entry(&hpp, h); - -			gtk_list_store_set(store, &iter, col_idx++, s, -1); -		} - -		list_for_each_entry(se, &hist_entry__sort_list, list) { -			if (se->elide) -				continue; - -			se->se_snprintf(h, s, ARRAY_SIZE(s), -					hists__col_len(hists, se->se_width_idx)); - -			gtk_list_store_set(store, &iter, col_idx++, s, -1); -		} -	} - -	gtk_container_add(GTK_CONTAINER(window), view); -} -  #ifdef HAVE_GTK_INFO_BAR -static GtkWidget *perf_gtk__setup_info_bar(void) +GtkWidget *perf_gtk__setup_info_bar(void)  {  	GtkWidget *info_bar;  	GtkWidget *label; @@ -220,7 +71,7 @@ static GtkWidget *perf_gtk__setup_info_bar(void)  }  #endif -static GtkWidget *perf_gtk__setup_statusbar(void) +GtkWidget *perf_gtk__setup_statusbar(void)  {  	GtkWidget *stbar;  	unsigned ctxid; @@ -234,81 +85,3 @@ static GtkWidget *perf_gtk__setup_statusbar(void)  	return stbar;  } - -int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, -				  const char *help, -				  void (*timer) (void *arg)__maybe_unused, -				  void *arg __maybe_unused, -				  int delay_secs __maybe_unused) -{ -	struct perf_evsel *pos; -	GtkWidget *vbox; -	GtkWidget *notebook; -	GtkWidget *info_bar; -	GtkWidget *statbar; -	GtkWidget *window; - -	signal(SIGSEGV, perf_gtk__signal); -	signal(SIGFPE,  perf_gtk__signal); -	signal(SIGINT,  perf_gtk__signal); -	signal(SIGQUIT, perf_gtk__signal); -	signal(SIGTERM, perf_gtk__signal); - -	window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - -	gtk_window_set_title(GTK_WINDOW(window), "perf report"); - -	g_signal_connect(window, "delete_event", gtk_main_quit, NULL); - -	pgctx = perf_gtk__activate_context(window); -	if (!pgctx) -		return -1; - -	vbox = gtk_vbox_new(FALSE, 0); - -	notebook = gtk_notebook_new(); - -	list_for_each_entry(pos, &evlist->entries, node) { -		struct hists *hists = &pos->hists; -		const char *evname = perf_evsel__name(pos); -		GtkWidget *scrolled_window; -		GtkWidget *tab_label; - -		scrolled_window = gtk_scrolled_window_new(NULL, NULL); - -		gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), -							GTK_POLICY_AUTOMATIC, -							GTK_POLICY_AUTOMATIC); - -		perf_gtk__show_hists(scrolled_window, hists); - -		tab_label = gtk_label_new(evname); - -		gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled_window, tab_label); -	} - -	gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0); - -	info_bar = perf_gtk__setup_info_bar(); -	if (info_bar) -		gtk_box_pack_start(GTK_BOX(vbox), info_bar, FALSE, FALSE, 0); - -	statbar = perf_gtk__setup_statusbar(); -	gtk_box_pack_start(GTK_BOX(vbox), statbar, FALSE, FALSE, 0); - -	gtk_container_add(GTK_CONTAINER(window), vbox); - -	gtk_widget_show_all(window); - -	perf_gtk__resize_window(window); - -	gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); - -	ui_helpline__push(help); - -	gtk_main(); - -	perf_gtk__deactivate_context(&pgctx); - -	return 0; -} diff --git a/tools/perf/ui/gtk/gtk.h b/tools/perf/ui/gtk/gtk.h index 687af0bba18..3d96785ef15 100644 --- a/tools/perf/ui/gtk/gtk.h +++ b/tools/perf/ui/gtk/gtk.h @@ -10,6 +10,7 @@  struct perf_gtk_context {  	GtkWidget *main_window; +	GtkWidget *notebook;  #ifdef HAVE_GTK_INFO_BAR  	GtkWidget *info_bar; @@ -30,9 +31,17 @@ struct perf_gtk_context *perf_gtk__activate_context(GtkWidget *window);  int perf_gtk__deactivate_context(struct perf_gtk_context **ctx);  void perf_gtk__init_helpline(void); +void perf_gtk__init_progress(void);  void perf_gtk__init_hpp(void); -#ifndef HAVE_GTK_INFO_BAR +void perf_gtk__signal(int sig); +void perf_gtk__resize_window(GtkWidget *window); +const char *perf_gtk__get_percent_color(double percent); +GtkWidget *perf_gtk__setup_statusbar(void); + +#ifdef HAVE_GTK_INFO_BAR +GtkWidget *perf_gtk__setup_info_bar(void); +#else  static inline GtkWidget *perf_gtk__setup_info_bar(void)  {  	return NULL; diff --git a/tools/perf/ui/gtk/helpline.c b/tools/perf/ui/gtk/helpline.c index 5db4432ff12..3388cbd1218 100644 --- a/tools/perf/ui/gtk/helpline.c +++ b/tools/perf/ui/gtk/helpline.c @@ -24,17 +24,7 @@ static void gtk_helpline_push(const char *msg)  			   pgctx->statbar_ctx_id, msg);  } -static struct ui_helpline gtk_helpline_fns = { -	.pop	= gtk_helpline_pop, -	.push	= gtk_helpline_push, -}; - -void perf_gtk__init_helpline(void) -{ -	helpline_fns = >k_helpline_fns; -} - -int perf_gtk__show_helpline(const char *fmt, va_list ap) +static int gtk_helpline_show(const char *fmt, va_list ap)  {  	int ret;  	char *ptr; @@ -54,3 +44,14 @@ int perf_gtk__show_helpline(const char *fmt, va_list ap)  	return ret;  } + +static struct ui_helpline gtk_helpline_fns = { +	.pop	= gtk_helpline_pop, +	.push	= gtk_helpline_push, +	.show	= gtk_helpline_show, +}; + +void perf_gtk__init_helpline(void) +{ +	helpline_fns = >k_helpline_fns; +} diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c new file mode 100644 index 00000000000..1e764a8ad25 --- /dev/null +++ b/tools/perf/ui/gtk/hists.c @@ -0,0 +1,312 @@ +#include "../evlist.h" +#include "../cache.h" +#include "../evsel.h" +#include "../sort.h" +#include "../hist.h" +#include "../helpline.h" +#include "gtk.h" + +#define MAX_COLUMNS			32 + +static int __percent_color_snprintf(char *buf, size_t size, double percent) +{ +	int ret = 0; +	const char *markup; + +	markup = perf_gtk__get_percent_color(percent); +	if (markup) +		ret += scnprintf(buf, size, markup); + +	ret += scnprintf(buf + ret, size - ret, " %6.2f%%", percent); + +	if (markup) +		ret += scnprintf(buf + ret, size - ret, "</span>"); + +	return ret; +} + + +static int __hpp__color_fmt(struct perf_hpp *hpp, struct hist_entry *he, +			    u64 (*get_field)(struct hist_entry *)) +{ +	int ret; +	double percent = 0.0; +	struct hists *hists = he->hists; + +	if (hists->stats.total_period) +		percent = 100.0 * get_field(he) / hists->stats.total_period; + +	ret = __percent_color_snprintf(hpp->buf, hpp->size, percent); + +	if (symbol_conf.event_group) { +		int prev_idx, idx_delta; +		struct perf_evsel *evsel = hists_to_evsel(hists); +		struct hist_entry *pair; +		int nr_members = evsel->nr_members; + +		if (nr_members <= 1) +			return ret; + +		prev_idx = perf_evsel__group_idx(evsel); + +		list_for_each_entry(pair, &he->pairs.head, pairs.node) { +			u64 period = get_field(pair); +			u64 total = pair->hists->stats.total_period; + +			evsel = hists_to_evsel(pair->hists); +			idx_delta = perf_evsel__group_idx(evsel) - prev_idx - 1; + +			while (idx_delta--) { +				/* +				 * zero-fill group members in the middle which +				 * have no sample +				 */ +				ret += __percent_color_snprintf(hpp->buf + ret, +								hpp->size - ret, +								0.0); +			} + +			percent = 100.0 * period / total; +			ret += __percent_color_snprintf(hpp->buf + ret, +							hpp->size - ret, +							percent); + +			prev_idx = perf_evsel__group_idx(evsel); +		} + +		idx_delta = nr_members - prev_idx - 1; + +		while (idx_delta--) { +			/* +			 * zero-fill group members at last which have no sample +			 */ +			ret += __percent_color_snprintf(hpp->buf + ret, +							hpp->size - ret, +							0.0); +		} +	} +	return ret; +} + +#define __HPP_COLOR_PERCENT_FN(_type, _field)					\ +static u64 he_get_##_field(struct hist_entry *he)				\ +{										\ +	return he->stat._field;							\ +}										\ +										\ +static int perf_gtk__hpp_color_##_type(struct perf_hpp *hpp,			\ +				       struct hist_entry *he)			\ +{										\ +	return __hpp__color_fmt(hpp, he, he_get_##_field);			\ +} + +__HPP_COLOR_PERCENT_FN(overhead, period) +__HPP_COLOR_PERCENT_FN(overhead_sys, period_sys) +__HPP_COLOR_PERCENT_FN(overhead_us, period_us) +__HPP_COLOR_PERCENT_FN(overhead_guest_sys, period_guest_sys) +__HPP_COLOR_PERCENT_FN(overhead_guest_us, period_guest_us) + +#undef __HPP_COLOR_PERCENT_FN + + +void perf_gtk__init_hpp(void) +{ +	perf_hpp__column_enable(PERF_HPP__OVERHEAD); + +	perf_hpp__init(); + +	perf_hpp__format[PERF_HPP__OVERHEAD].color = +				perf_gtk__hpp_color_overhead; +	perf_hpp__format[PERF_HPP__OVERHEAD_SYS].color = +				perf_gtk__hpp_color_overhead_sys; +	perf_hpp__format[PERF_HPP__OVERHEAD_US].color = +				perf_gtk__hpp_color_overhead_us; +	perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].color = +				perf_gtk__hpp_color_overhead_guest_sys; +	perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].color = +				perf_gtk__hpp_color_overhead_guest_us; +} + +static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) +{ +	struct perf_hpp_fmt *fmt; +	GType col_types[MAX_COLUMNS]; +	GtkCellRenderer *renderer; +	struct sort_entry *se; +	GtkListStore *store; +	struct rb_node *nd; +	GtkWidget *view; +	int col_idx; +	int nr_cols; +	char s[512]; + +	struct perf_hpp hpp = { +		.buf		= s, +		.size		= sizeof(s), +		.ptr		= hists_to_evsel(hists), +	}; + +	nr_cols = 0; + +	perf_hpp__for_each_format(fmt) +		col_types[nr_cols++] = G_TYPE_STRING; + +	list_for_each_entry(se, &hist_entry__sort_list, list) { +		if (se->elide) +			continue; + +		col_types[nr_cols++] = G_TYPE_STRING; +	} + +	store = gtk_list_store_newv(nr_cols, col_types); + +	view = gtk_tree_view_new(); + +	renderer = gtk_cell_renderer_text_new(); + +	col_idx = 0; + +	perf_hpp__for_each_format(fmt) { +		fmt->header(&hpp); + +		gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), +							    -1, ltrim(s), +							    renderer, "markup", +							    col_idx++, NULL); +	} + +	list_for_each_entry(se, &hist_entry__sort_list, list) { +		if (se->elide) +			continue; + +		gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), +							    -1, se->se_header, +							    renderer, "text", +							    col_idx++, NULL); +	} + +	gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store)); + +	g_object_unref(GTK_TREE_MODEL(store)); + +	for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { +		struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); +		GtkTreeIter iter; + +		if (h->filtered) +			continue; + +		gtk_list_store_append(store, &iter); + +		col_idx = 0; + +		perf_hpp__for_each_format(fmt) { +			if (fmt->color) +				fmt->color(&hpp, h); +			else +				fmt->entry(&hpp, h); + +			gtk_list_store_set(store, &iter, col_idx++, s, -1); +		} + +		list_for_each_entry(se, &hist_entry__sort_list, list) { +			if (se->elide) +				continue; + +			se->se_snprintf(h, s, ARRAY_SIZE(s), +					hists__col_len(hists, se->se_width_idx)); + +			gtk_list_store_set(store, &iter, col_idx++, s, -1); +		} +	} + +	gtk_container_add(GTK_CONTAINER(window), view); +} + +int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, +				  const char *help, +				  struct hist_browser_timer *hbt __maybe_unused) +{ +	struct perf_evsel *pos; +	GtkWidget *vbox; +	GtkWidget *notebook; +	GtkWidget *info_bar; +	GtkWidget *statbar; +	GtkWidget *window; + +	signal(SIGSEGV, perf_gtk__signal); +	signal(SIGFPE,  perf_gtk__signal); +	signal(SIGINT,  perf_gtk__signal); +	signal(SIGQUIT, perf_gtk__signal); +	signal(SIGTERM, perf_gtk__signal); + +	window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + +	gtk_window_set_title(GTK_WINDOW(window), "perf report"); + +	g_signal_connect(window, "delete_event", gtk_main_quit, NULL); + +	pgctx = perf_gtk__activate_context(window); +	if (!pgctx) +		return -1; + +	vbox = gtk_vbox_new(FALSE, 0); + +	notebook = gtk_notebook_new(); + +	gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0); + +	info_bar = perf_gtk__setup_info_bar(); +	if (info_bar) +		gtk_box_pack_start(GTK_BOX(vbox), info_bar, FALSE, FALSE, 0); + +	statbar = perf_gtk__setup_statusbar(); +	gtk_box_pack_start(GTK_BOX(vbox), statbar, FALSE, FALSE, 0); + +	gtk_container_add(GTK_CONTAINER(window), vbox); + +	list_for_each_entry(pos, &evlist->entries, node) { +		struct hists *hists = &pos->hists; +		const char *evname = perf_evsel__name(pos); +		GtkWidget *scrolled_window; +		GtkWidget *tab_label; +		char buf[512]; +		size_t size = sizeof(buf); + +		if (symbol_conf.event_group) { +			if (!perf_evsel__is_group_leader(pos)) +				continue; + +			if (pos->nr_members > 1) { +				perf_evsel__group_desc(pos, buf, size); +				evname = buf; +			} +		} + +		scrolled_window = gtk_scrolled_window_new(NULL, NULL); + +		gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), +							GTK_POLICY_AUTOMATIC, +							GTK_POLICY_AUTOMATIC); + +		perf_gtk__show_hists(scrolled_window, hists); + +		tab_label = gtk_label_new(evname); + +		gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled_window, tab_label); +	} + +	gtk_widget_show_all(window); + +	perf_gtk__resize_window(window); + +	gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); + +	ui_helpline__push(help); + +	gtk_main(); + +	perf_gtk__deactivate_context(&pgctx); + +	return 0; +} diff --git a/tools/perf/ui/gtk/progress.c b/tools/perf/ui/gtk/progress.c new file mode 100644 index 00000000000..482bcf3df9b --- /dev/null +++ b/tools/perf/ui/gtk/progress.c @@ -0,0 +1,59 @@ +#include <inttypes.h> + +#include "gtk.h" +#include "../progress.h" +#include "util.h" + +static GtkWidget *dialog; +static GtkWidget *progress; + +static void gtk_progress_update(u64 curr, u64 total, const char *title) +{ +	double fraction = total ? 1.0 * curr / total : 0.0; +	char buf[1024]; + +	if (dialog == NULL) { +		GtkWidget *vbox = gtk_vbox_new(TRUE, 5); +		GtkWidget *label = gtk_label_new(title); + +		dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL); +		progress = gtk_progress_bar_new(); + +		gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, FALSE, 3); +		gtk_box_pack_start(GTK_BOX(vbox), progress, TRUE, TRUE, 3); + +		gtk_container_add(GTK_CONTAINER(dialog), vbox); + +		gtk_window_set_title(GTK_WINDOW(dialog), "perf"); +		gtk_window_resize(GTK_WINDOW(dialog), 300, 80); +		gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER); + +		gtk_widget_show_all(dialog); +	} + +	gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), fraction); +	snprintf(buf, sizeof(buf), "%"PRIu64" / %"PRIu64, curr, total); +	gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress), buf); + +	/* we didn't call gtk_main yet, so do it manually */ +	while (gtk_events_pending()) +		gtk_main_iteration(); +} + +static void gtk_progress_finish(void) +{ +	/* this will also destroy all of its children */ +	gtk_widget_destroy(dialog); + +	dialog = NULL; +} + +static struct ui_progress gtk_progress_fns = { +	.update		= gtk_progress_update, +	.finish		= gtk_progress_finish, +}; + +void perf_gtk__init_progress(void) +{ +	progress_fns = >k_progress_fns; +} diff --git a/tools/perf/ui/gtk/setup.c b/tools/perf/ui/gtk/setup.c index 3c4c6ef7828..6c2dd2e423f 100644 --- a/tools/perf/ui/gtk/setup.c +++ b/tools/perf/ui/gtk/setup.c @@ -8,7 +8,9 @@ int perf_gtk__init(void)  {  	perf_error__register(&perf_gtk_eops);  	perf_gtk__init_helpline(); +	perf_gtk__init_progress();  	perf_gtk__init_hpp(); +  	return gtk_init_check(NULL, NULL) ? 0 : -1;  } diff --git a/tools/perf/ui/gtk/util.c b/tools/perf/ui/gtk/util.c index ccb046aac98..c06942a41c7 100644 --- a/tools/perf/ui/gtk/util.c +++ b/tools/perf/ui/gtk/util.c @@ -111,14 +111,3 @@ struct perf_error_ops perf_gtk_eops = {  	.warning	= perf_gtk__warning_statusbar,  #endif  }; - -/* - * FIXME: Functions below should be implemented properly. - *        For now, just add stubs for NO_NEWT=1 build. - */ -#ifndef NEWT_SUPPORT -void ui_progress__update(u64 curr __maybe_unused, u64 total __maybe_unused, -			 const char *title __maybe_unused) -{ -} -#endif  |