aboutsummaryrefslogtreecommitdiffstats
path: root/trace-graph.c
diff options
context:
space:
mode:
Diffstat (limited to 'trace-graph.c')
-rw-r--r--trace-graph.c301
1 files changed, 208 insertions, 93 deletions
diff --git a/trace-graph.c b/trace-graph.c
index e91dc6e..dd99b4b 100644
--- a/trace-graph.c
+++ b/trace-graph.c
@@ -54,6 +54,14 @@ static void convert_nano(unsigned long long time, unsigned long *sec,
54 *usec = (time / 1000) % 1000000; 54 *usec = (time / 1000) % 1000000;
55} 55}
56 56
57static void print_time(unsigned long long time)
58{
59 unsigned long sec, usec;
60
61 convert_nano(time, &sec, &usec);
62 printf("%lu.%06lu", sec, usec);
63}
64
57static void update_with_backend(struct graph_info *ginfo, 65static void update_with_backend(struct graph_info *ginfo,
58 gint x, gint y, 66 gint x, gint y,
59 gint width, gint height) 67 gint width, gint height)
@@ -94,7 +102,7 @@ button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
94 if (event->button != 1) 102 if (event->button != 1)
95 return TRUE; 103 return TRUE;
96 104
97 ginfo->start_x = event->x; 105 ginfo->press_x = event->x;
98 ginfo->last_x = 0; 106 ginfo->last_x = 0;
99 107
100 draw_line(widget, event->x, ginfo); 108 draw_line(widget, event->x, ginfo);
@@ -115,27 +123,6 @@ static void clear_last_line(GtkWidget *widget, struct graph_info *ginfo)
115 update_with_backend(ginfo, x, 0, x+2, widget->allocation.height); 123 update_with_backend(ginfo, x, 0, x+2, widget->allocation.height);
116} 124}
117 125
118static void
119save_line(GtkWidget *widget, struct graph_info *ginfo)
120{
121 gint x, y;
122
123 x = ginfo->last_x + ginfo->mov_w;
124 y = ginfo->last_y + ginfo->mov_h;
125
126 printf("save %d,%d to %d,%d, width=%d height=%d\n",
127 x,y, ginfo->last_x, ginfo->last_y,
128 ginfo->mov_w, ginfo->mov_h);
129
130 gdk_draw_line(widget->window, widget->style->black_gc,
131 ginfo->last_x, ginfo->last_y,
132 x, y);
133
134 gdk_draw_line(ginfo->curr_pixmap, widget->style->black_gc,
135 ginfo->last_x, ginfo->last_y,
136 x, y);
137}
138
139static void print_rec_info(struct record *record, struct pevent *pevent, int cpu) 126static void print_rec_info(struct record *record, struct pevent *pevent, int cpu)
140{ 127{
141 struct trace_seq s; 128 struct trace_seq s;
@@ -373,17 +360,11 @@ motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer data)
373 if (ginfo->last_x) 360 if (ginfo->last_x)
374 clear_last_line(widget, ginfo); 361 clear_last_line(widget, ginfo);
375 ginfo->last_x = x; 362 ginfo->last_x = x;
376 draw_line(widget, ginfo->start_x, ginfo); 363 draw_line(widget, ginfo->press_x, ginfo);
377 draw_line(widget, x, ginfo); 364 draw_line(widget, x, ginfo);
378 return TRUE; 365 return TRUE;
379 } 366 }
380 367
381 if (ginfo->draw_line) {
382 ginfo->last_x = x;
383// draw_line(widget, x, y, ginfo);
384 return TRUE;
385 }
386
387 for (cpu = 0; cpu < ginfo->cpus; cpu++) { 368 for (cpu = 0; cpu < ginfo->cpus; cpu++) {
388 if (y >= CPU_TOP(cpu) && y <= CPU_BOTTOM(cpu)) { 369 if (y >= CPU_TOP(cpu) && y <= CPU_BOTTOM(cpu)) {
389 draw_cpu_info(ginfo, cpu, x, y); 370 draw_cpu_info(ginfo, cpu, x, y);
@@ -393,26 +374,58 @@ motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer data)
393 return TRUE; 374 return TRUE;
394} 375}
395 376
377static void update_graph(struct graph_info *ginfo, gdouble percent)
378{
379 ginfo->full_width *= percent;
380 ginfo->resolution =
381 (gdouble)ginfo->full_width / (gdouble)(ginfo->end_time -
382 ginfo->start_time);
383 ginfo->start_x *= percent;
384}
385
386static void update_graph_to_start_x(struct graph_info *ginfo)
387{
388 ginfo->view_start_time = ginfo->start_x / ginfo->resolution +
389 ginfo->start_time;
390
391 ginfo->view_end_time = ginfo->draw_width / ginfo->resolution +
392 ginfo->view_start_time;
393}
394
395static void reset_graph(struct graph_info *ginfo, gdouble view_width)
396{
397 ginfo->full_width = view_width;
398 ginfo->draw_width = 0;
399 ginfo->view_start_time = ginfo->start_time;
400 ginfo->view_end_time = ginfo->end_time;
401 ginfo->start_x = 0;
402}
403
396static void zoom_in_window(struct graph_info *ginfo, gint start, gint end) 404static void zoom_in_window(struct graph_info *ginfo, gint start, gint end)
397{ 405{
398 gdouble view_width; 406 gdouble view_width;
399 gdouble new_width; 407 gdouble new_width;
408 gdouble select_width;
400 gdouble curr_width; 409 gdouble curr_width;
401// unsigned long long start_time; 410 gdouble mid;
402// unsigned long long end_time; 411 gdouble percent;
412 gint old_width = ginfo->draw_width;
403 413
404 g_assert(start < end); 414 g_assert(start < end);
405 g_assert(ginfo->vadj); 415 g_assert(ginfo->vadj);
406 416
417 printf("*** started with ");
418 print_time(start / ginfo->resolution + ginfo->view_start_time);
419 printf("\n");
420
407 view_width = gtk_adjustment_get_page_size(ginfo->vadj); 421 view_width = gtk_adjustment_get_page_size(ginfo->vadj);
422 select_width = end - start;
423 percent = view_width / select_width;
408 424
409 new_width = end - start; 425 update_graph(ginfo, percent);
410 426
411 curr_width = ginfo->draw->allocation.width; 427 curr_width = ginfo->draw->allocation.width;
412 428 new_width = curr_width * percent;
413 ginfo->vadj_value = (gdouble)start * view_width / new_width;
414
415 new_width = curr_width * (view_width / new_width);
416 429
417 printf("width=%d\n", ginfo->draw->allocation.width); 430 printf("width=%d\n", ginfo->draw->allocation.width);
418 if (ginfo->vadj) { 431 if (ginfo->vadj) {
@@ -423,16 +436,103 @@ static void zoom_in_window(struct graph_info *ginfo, gint start, gint end)
423 436
424 ginfo->draw_width = new_width; 437 ginfo->draw_width = new_width;
425 438
426 if (ginfo->draw_width > MAX_WIDTH) 439 if (ginfo->draw_width > MAX_WIDTH) {
440 gint new_start;
441 gint new_end;
442
443 /*
444 * The drawing is now greater than our max. We must
445 * limit the maximum size of the drawing area or
446 * we risk running out of X resources.
447 *
448 * We will now shorten the trace to that of what will
449 * fit in this zoomed area.
450 */
427 ginfo->draw_width = MAX_WIDTH; 451 ginfo->draw_width = MAX_WIDTH;
428 452
453 mid = start + (end - start) / 2;
454 mid *= percent;
455
456 /*
457 * mid now points to the center of the viewable area
458 * if the draw area was of new_width.
459 *
460 * new_start new_end
461 * +------------------------------------------------+
462 * | | | |
463 * | | | |
464 * +------------------------------------------------+
465 * ^ ^
466 * | mid
467 * old view start
468 *
469 */
470
471 new_start = mid - MAX_WIDTH / 2;
472 new_end = new_start + MAX_WIDTH;
473 if (new_start < 0) {
474 /* First check if there's a start available in full */
475 if (ginfo->start_x) {
476 ginfo->start_x += new_start;
477 if (ginfo->start_x < 0) {
478 new_start = ginfo->start_x;
479 ginfo->start_x = 0;
480 } else
481 new_start = 0;
482 }
483 new_end += -new_start;
484 new_start = 0;
485 } else if (new_end > ginfo->full_width) {
486 new_start -= new_end - ginfo->full_width;
487 new_end = ginfo->full_width;
488 g_assert(new_start >= 0);
489 }
490
491 ginfo->start_x += new_start;
492
493 update_graph_to_start_x(ginfo);
494
495 printf("new start/end =%d/%d full:%d start_time:",
496 new_start, new_end, ginfo->full_width);
497 print_time(ginfo->view_start_time);
498 printf("\n");
499
500 /* Adjust start to be the location for the vadj */
501 start = (mid - new_start) / percent - (end - start) / 2;
502 }
503
504 ginfo->vadj_value = (gdouble)start * view_width / select_width;
429 if (ginfo->vadj_value > (ginfo->draw_width - view_width)) 505 if (ginfo->vadj_value > (ginfo->draw_width - view_width))
430 ginfo->vadj_value = ginfo->draw_width - view_width; 506 ginfo->vadj_value = ginfo->draw_width - view_width;
431 507
432 printf("new width=%d\n", ginfo->draw_width); 508 printf("new width=%d\n", ginfo->draw_width);
509
510 /* make sure the width is sent */
511 if (ginfo->draw_width == old_width)
512 gtk_widget_set_size_request(ginfo->draw, ginfo->draw_width - 1,
513 ginfo->draw_height);
433 gtk_widget_set_size_request(ginfo->draw, ginfo->draw_width, ginfo->draw_height); 514 gtk_widget_set_size_request(ginfo->draw, ginfo->draw_width, ginfo->draw_height);
434 515
435 printf("set val %f\n", ginfo->vadj_value); 516 printf("set val %f\n", ginfo->vadj_value);
517
518
519 printf("*** ended with with ");
520 print_time(ginfo->vadj_value / ginfo->resolution + ginfo->view_start_time);
521 printf("\n");
522
523}
524
525static gboolean
526value_changed(GtkWidget *widget, gpointer data)
527{
528 struct graph_info *ginfo = data;
529 GtkAdjustment *adj = GTK_ADJUSTMENT(widget);
530
531 printf("value = %f\n",
532 gtk_adjustment_get_value(adj));
533
534 return TRUE;
535
436} 536}
437 537
438static void zoom_out_window(struct graph_info *ginfo, gint start, gint end) 538static void zoom_out_window(struct graph_info *ginfo, gint start, gint end)
@@ -441,39 +541,70 @@ static void zoom_out_window(struct graph_info *ginfo, gint start, gint end)
441 gdouble divider; 541 gdouble divider;
442 gdouble curr_width; 542 gdouble curr_width;
443 gdouble new_width; 543 gdouble new_width;
444 gdouble value; 544 gdouble mid;
445// unsigned long long start_time; 545 gdouble start_x;
446// unsigned long long end_time; 546 unsigned long long time;
547 gint old_width = ginfo->draw_width;
447 548
448 g_assert(start > end); 549 g_assert(start > end);
449 g_assert(ginfo->vadj); 550 g_assert(ginfo->vadj);
450 551
451 view_width = gtk_adjustment_get_page_size(ginfo->vadj); 552 view_width = gtk_adjustment_get_page_size(ginfo->vadj);
553 start_x = gtk_adjustment_get_value(ginfo->vadj);
554 mid = start_x + view_width / 2;
555
556 time = mid / ginfo->resolution + ginfo->view_start_time;
452 557
453 divider = start - end; 558 divider = start - end;
454 559
455 curr_width = ginfo->draw->allocation.width; 560 curr_width = ginfo->draw->allocation.width;
456
457 new_width = curr_width / divider; 561 new_width = curr_width / divider;
458 562
563 update_graph(ginfo, 1 / divider);
564
459 printf("width=%d\n", ginfo->draw->allocation.width); 565 printf("width=%d\n", ginfo->draw->allocation.width);
460 if (ginfo->vadj) {
461 printf("adj:%f-%f\n", gtk_adjustment_get_upper(ginfo->vadj),
462 gtk_adjustment_get_lower(ginfo->vadj));
463 } else
464 printf("no adjustment\n");
465 566
466 ginfo->draw_width = new_width; 567 ginfo->draw_width = new_width;
467 568
468 if (ginfo->draw_width < view_width) 569 printf("draw_width=%d full_width=%d\n", ginfo->draw_width, ginfo->full_width);
469 ginfo->draw_width = 0; 570 if (ginfo->full_width < view_width) {
571 reset_graph(ginfo, view_width);
572 time = ginfo->view_start_time;
573
574 } else if (ginfo->draw_width < ginfo->full_width) {
575 if (ginfo->full_width < MAX_WIDTH) {
576 ginfo->draw_width = ginfo->full_width;
577 ginfo->view_start_time = ginfo->start_time;
578 ginfo->view_end_time = ginfo->end_time;
579 ginfo->start_x = 0;
580 } else {
581 ginfo->draw_width = MAX_WIDTH;
582 mid /= divider;
583 mid += ginfo->start_x;
584
585 /* mid now is the current mid with full_width */
586 ginfo->start_x = mid - MAX_WIDTH / 2;
587 if (ginfo->start_x < 0)
588 ginfo->start_x = 0;
589
590 update_graph_to_start_x(ginfo);
591 }
592 }
470 593
471 printf("new width=%d\n", ginfo->draw_width); 594 printf("new width=%d\n", ginfo->draw_width);
595
596 /* make sure the width is sent */
597 if (ginfo->draw_width == old_width)
598 gtk_widget_set_size_request(ginfo->draw, ginfo->draw_width - 1,
599 ginfo->draw_height);
472 gtk_widget_set_size_request(ginfo->draw, ginfo->draw_width, ginfo->draw_height); 600 gtk_widget_set_size_request(ginfo->draw, ginfo->draw_width, ginfo->draw_height);
473 601
474 value = gtk_adjustment_get_value(ginfo->vadj); 602 mid = (time - ginfo->view_start_time) * ginfo->resolution;
475 if (value > new_width - view_width) 603 start_x = mid - view_width / 2;
476 ginfo->vadj_value = new_width - view_width; 604 if (start_x < 0)
605 start_x = 0;
606
607 ginfo->vadj_value = start_x;
477} 608}
478 609
479static gboolean 610static gboolean
@@ -484,29 +615,18 @@ button_release_event(GtkWidget *widget, GdkEventMotion *event, gpointer data)
484 if (ginfo->line_active) { 615 if (ginfo->line_active) {
485 ginfo->line_active = FALSE; 616 ginfo->line_active = FALSE;
486 clear_last_line(widget, ginfo); 617 clear_last_line(widget, ginfo);
487 ginfo->last_x = ginfo->start_x; 618 ginfo->last_x = ginfo->press_x;
488 clear_last_line(widget, ginfo); 619 clear_last_line(widget, ginfo);
489 620
490 if (event->x > ginfo->start_x) { 621 if (event->x > ginfo->press_x) {
491 /* make a decent zoom */ 622 /* make a decent zoom */
492 if (event->x - ginfo->start_x < 10) 623 if (event->x - ginfo->press_x < 10)
493 return TRUE; 624 return TRUE;
494 zoom_in_window(ginfo, ginfo->start_x, event->x); 625 zoom_in_window(ginfo, ginfo->press_x, event->x);
495 return TRUE; 626 } else if (event->x < ginfo->press_x)
496 } else if (event->x < ginfo->start_x) { 627 zoom_out_window(ginfo, ginfo->press_x, event->x);
497 zoom_out_window(ginfo, ginfo->start_x, event->x);
498 return TRUE;
499 } else
500 return TRUE;
501 } 628 }
502 629
503 printf("RELEASE %s\n", ginfo->save ? "save" : "");
504
505 ginfo->draw_line = FALSE;
506
507 if (ginfo->save)
508 save_line(widget, ginfo);
509
510 return TRUE; 630 return TRUE;
511} 631}
512 632
@@ -535,7 +655,7 @@ static void set_color_by_pid(GtkWidget *widget, GdkGC *gc, gint pid)
535} 655}
536 656
537static void draw_cpu(struct graph_info *ginfo, gint cpu, 657static void draw_cpu(struct graph_info *ginfo, gint cpu,
538 gint old_width, gint new_width) 658 gint new_width)
539{ 659{
540 gint height = CPU_MIDDLE(cpu); 660 gint height = CPU_MIDDLE(cpu);
541 struct record *record; 661 struct record *record;
@@ -632,7 +752,7 @@ static void draw_timeline(struct graph_info *ginfo, gint width)
632 width-1, height, width-1, height + 5); 752 width-1, height, width-1, height + 5);
633 753
634 /* --- draw starting time --- */ 754 /* --- draw starting time --- */
635 convert_nano(ginfo->start_time, &sec, &usec); 755 convert_nano(ginfo->view_start_time, &sec, &usec);
636 trace_seq_init(&s); 756 trace_seq_init(&s);
637 trace_seq_printf(&s, "%lu.%06lu", sec, usec); 757 trace_seq_printf(&s, "%lu.%06lu", sec, usec);
638 758
@@ -645,7 +765,7 @@ static void draw_timeline(struct graph_info *ginfo, gint width)
645 765
646 766
647 /* --- draw ending time --- */ 767 /* --- draw ending time --- */
648 convert_nano(ginfo->end_time, &sec, &usec); 768 convert_nano(ginfo->view_end_time, &sec, &usec);
649 trace_seq_init(&s); 769 trace_seq_init(&s);
650 trace_seq_printf(&s, "%lu.%06lu", sec, usec); 770 trace_seq_printf(&s, "%lu.%06lu", sec, usec);
651 771
@@ -680,8 +800,8 @@ static void draw_timeline(struct graph_info *ginfo, gint width)
680 } 800 }
681} 801}
682 802
683static void draw_info(struct graph_info *ginfo, gint old_width, gint old_height, 803static void draw_info(struct graph_info *ginfo,
684 gint new_width, gint new_height) 804 gint new_width)
685{ 805{
686 gint cpu; 806 gint cpu;
687 807
@@ -692,7 +812,7 @@ static void draw_info(struct graph_info *ginfo, gint old_width, gint old_height,
692 812
693 813
694 for (cpu = 0; cpu < ginfo->cpus; cpu++) 814 for (cpu = 0; cpu < ginfo->cpus; cpu++)
695 draw_cpu(ginfo, cpu, old_width, new_width); 815 draw_cpu(ginfo, cpu, new_width);
696 816
697} 817}
698 818
@@ -701,29 +821,19 @@ configure_event(GtkWidget *widget, GdkEventMotion *event, gpointer data)
701{ 821{
702 struct graph_info *ginfo = data; 822 struct graph_info *ginfo = data;
703 GdkPixmap *old_pix; 823 GdkPixmap *old_pix;
704 gint old_w, old_h;
705
706 if (0 && widget->allocation.width < ginfo->max_width &&
707 widget->allocation.height < ginfo->max_height)
708 return TRUE;
709
710 old_w = ginfo->max_width;
711 old_h = ginfo->max_height;
712 824
713// gtk_widget_set_size_request(widget, 0, ginfo->draw_height); 825// gtk_widget_set_size_request(widget, 0, ginfo->draw_height);
714 826
715 827
716 if (widget->allocation.width > ginfo->max_width)
717 ginfo->max_width = widget->allocation.width;
718
719 if (widget->allocation.height > ginfo->max_height)
720 ginfo->max_height = widget->allocation.height;
721
722 old_pix = ginfo->curr_pixmap; 828 old_pix = ginfo->curr_pixmap;
723 829
830 /* initialize full width if needed */
831 if (!ginfo->full_width)
832 ginfo->full_width = widget->allocation.width;
833
724 ginfo->curr_pixmap = gdk_pixmap_new(widget->window, 834 ginfo->curr_pixmap = gdk_pixmap_new(widget->window,
725 ginfo->max_width, 835 widget->allocation.width,
726 ginfo->max_height, 836 widget->allocation.height,
727 -1); 837 -1);
728 838
729 gdk_draw_rectangle(ginfo->curr_pixmap, 839 gdk_draw_rectangle(ginfo->curr_pixmap,
@@ -733,9 +843,7 @@ configure_event(GtkWidget *widget, GdkEventMotion *event, gpointer data)
733 widget->allocation.width, 843 widget->allocation.width,
734 widget->allocation.height); 844 widget->allocation.height);
735 845
736 draw_info(ginfo, old_w, old_h, 846 draw_info(ginfo, widget->allocation.width);
737 widget->allocation.width,
738 widget->allocation.height);
739 847
740 if (old_pix) { 848 if (old_pix) {
741#if 0 849#if 0
@@ -752,7 +860,11 @@ configure_event(GtkWidget *widget, GdkEventMotion *event, gpointer data)
752 if (!ginfo->vadj_value) 860 if (!ginfo->vadj_value)
753 return TRUE; 861 return TRUE;
754 862
863// gtk_adjustment_set_lower(ginfo->vadj, -100.0);
755 gtk_adjustment_set_value(ginfo->vadj, ginfo->vadj_value); 864 gtk_adjustment_set_value(ginfo->vadj, ginfo->vadj_value);
865
866
867 /* debug */
756 ginfo->vadj_value = gtk_adjustment_get_value(ginfo->vadj); 868 ginfo->vadj_value = gtk_adjustment_get_value(ginfo->vadj);
757 printf("get val %f\n", ginfo->vadj_value); 869 printf("get val %f\n", ginfo->vadj_value);
758 ginfo->vadj_value = 0.0; 870 ginfo->vadj_value = 0.0;
@@ -793,6 +905,9 @@ create_drawing_area(struct tracecmd_input *handle, GtkScrolledWindow *scrollwin)
793 ginfo->draw_height = CPU_SPACE(ginfo->cpus); 905 ginfo->draw_height = CPU_SPACE(ginfo->cpus);
794 ginfo->vadj = gtk_scrolled_window_get_hadjustment(scrollwin); 906 ginfo->vadj = gtk_scrolled_window_get_hadjustment(scrollwin);
795 907
908 gtk_signal_connect(GTK_OBJECT(ginfo->vadj), "value_changed",
909 (GtkSignalFunc) value_changed, ginfo);
910
796 for (cpu = 0; cpu < ginfo->cpus; cpu++) { 911 for (cpu = 0; cpu < ginfo->cpus; cpu++) {
797 struct record *record; 912 struct record *record;
798 913