add multiplot example

Signed-off-by: Yordan Karadzhov <ykaradzhov@vmware.com>
diff --git a/kernel-shark-qt/examples/multiplot.cpp b/kernel-shark-qt/examples/multiplot.cpp
new file mode 100644
index 0000000..f166aa5
--- /dev/null
+++ b/kernel-shark-qt/examples/multiplot.cpp
@@ -0,0 +1,162 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright (C) 2018 VMware Inc, Yordan Karadzhov <y.karadz@gmail.com>
+ */
+
+// C
+#include <stdint.h>
+
+// C++
+#include <vector>
+#include <iostream>
+
+// OpenGL
+#include <GL/freeglut.h>
+
+// KernelShark
+#include "libkshark.h"
+#include "KsPlotTools.hpp"
+
+#define GRAPH_HEIGHT	40   // width of the graph in pixels
+#define GRAPH_H_MARGIN	50   // size of the white space surrounding the graph
+#define WINDOW_WIDTH	1200  // width of the screen window in pixels
+#define WINDOW_HEIGHT	720  // height of the scrren window in pixels
+
+using namespace std;
+
+kshark_trace_histo histo_m;
+vector<KsPlot::Graph *> graphs;
+int *stream_ids;
+
+void calib(kshark_entry *e, int64_t *atgv) {
+	e->ts += atgv[0];
+}
+
+void plot()
+{
+	KsPlot::Color::setRainbowFrequency(.9);
+	KsPlot::ColorTable pidColors = KsPlot::getTaskColorTable();
+	vector<KsPlot::Graph *>::iterator it;
+	kshark_context *kshark_ctx(nullptr);
+	struct kshark_data_stream *stream;
+	KsPlot::Graph *graph;
+	int base, nCPUs, sd;
+
+	if (!kshark_instance(&kshark_ctx))
+		return;
+
+	for (int d = 0; d < kshark_ctx->n_streams; ++d) {
+		sd = stream_ids[d];
+		stream = kshark_get_data_stream(kshark_ctx, sd);
+		nCPUs = tep_get_cpus(stream->pevent);
+		for (int cpu = 0; cpu < nCPUs; ++cpu) {
+// 			graph = new KsPlot::Graph(&histos[d], &colors);
+			graph = new KsPlot::Graph(&histo_m, &pidColors,
+							    &pidColors);
+
+			/* Set the dimensions of the Graph. */
+			graph->setHeight(GRAPH_HEIGHT);
+			graph->setHMargin(GRAPH_H_MARGIN);
+
+			/*
+			 * Set the Y coordinate of the Graph's base.
+			 * Remember that the "Y" coordinate is inverted.
+			 */
+			base = 1.7 * GRAPH_HEIGHT * (graphs.size() + 1);
+			graph->setBase(base);
+
+			graph->fillCPUGraph(sd, cpu);
+
+			/* Add the Graph. */
+			graphs.push_back(graph);
+		}
+	}
+
+	/* Clear the screen. */
+	glClear(GL_COLOR_BUFFER_BIT);
+
+	/* Draw all graphs. */
+	for (auto &g: graphs)
+		g->draw();
+
+	glFlush();
+}
+
+int main(int argc, char **argv)
+{
+	vector<kshark_entry **> data(argc - 1, nullptr);
+	kshark_entry ** data_m;
+	vector<size_t> nRows(argc - 1, 0);
+	kshark_context *kshark_ctx(nullptr);
+	int nBins;
+	size_t r, tot;
+	int64_t timeShift;
+
+	/* Create a new kshark session. */
+	if (!kshark_instance(&kshark_ctx))
+		return 1;
+
+	if (argc != 3)
+		return 1;
+
+	for (int i = 1; i < argc; ++i) {
+		if (kshark_open(kshark_ctx, argv[i]) < 0) {
+			cerr << "Unable to load file " << argv[i] << endl;
+			return 1;
+		}
+	}
+
+	stream_ids = kshark_all_streams(kshark_ctx);
+	for (int d = 0; d < kshark_ctx->n_streams; ++d) {
+		nRows[d] = kshark_load_data_entries(kshark_ctx,
+						    stream_ids[d],
+						    &data[d]);
+	}
+
+	timeShift = data[0][0]->ts - data[1][0]->ts;
+	tot = nRows[0] + nRows[1];
+	printf("%lu  %lu  t0 %lu\n",  data[0][0]->ts, data[1][0]->ts, timeShift);
+	data_m = kshark_data_merge(data[0], nRows[0],
+				   data[1], nRows[1],
+				   calib, &timeShift);
+
+	for (size_t i = 1; i < tot; ++i) {
+		if (data_m[i]->ts < data_m[i-1]->ts)
+			break;
+	}
+
+	nBins = WINDOW_WIDTH - 2 * GRAPH_H_MARGIN;
+
+	ksmodel_init(&histo_m);
+	ksmodel_set_bining(&histo_m, nBins, data_m[0]->ts,
+					    data_m[tot - 1]->ts);
+
+	/* Fill the model with data and calculate its state. */
+	ksmodel_fill(&histo_m, data_m, tot);
+
+	glutInit(&argc, argv);
+	ksplot_make_scene(WINDOW_WIDTH, WINDOW_HEIGHT);
+	ksplot_init_opengl(1);
+
+	/* Display graphs. */
+	glutDisplayFunc(plot);
+	glutMainLoop();
+
+	/* Free the memory. */
+	free(stream_ids);
+
+	for (size_t d = 0; d < data.size(); ++d) {
+		for (r = 0; r < nRows[d]; ++r)
+			free(data[d][r]);
+
+		free(data[d]);
+	}
+
+	free(data_m);
+
+	/* Close the session. */
+	kshark_free(kshark_ctx);
+
+	return 0;
+}
diff --git a/kernel-shark/examples/CMakeLists.txt b/kernel-shark/examples/CMakeLists.txt
index 0b18e54..1af98f6 100644
--- a/kernel-shark/examples/CMakeLists.txt
+++ b/kernel-shark/examples/CMakeLists.txt
@@ -27,3 +27,7 @@
 message(STATUS "multiload")
 add_executable(mload          multiload.c)
 target_link_libraries(mload   kshark)
+
+message(STATUS "multiplot")
+add_executable(mplot          multiplot.cpp)
+target_link_libraries(mplot   kshark-plot)
diff --git a/kernel-shark/examples/multiplot.cpp b/kernel-shark/examples/multiplot.cpp
new file mode 100644
index 0000000..f166aa5
--- /dev/null
+++ b/kernel-shark/examples/multiplot.cpp
@@ -0,0 +1,162 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright (C) 2018 VMware Inc, Yordan Karadzhov <y.karadz@gmail.com>
+ */
+
+// C
+#include <stdint.h>
+
+// C++
+#include <vector>
+#include <iostream>
+
+// OpenGL
+#include <GL/freeglut.h>
+
+// KernelShark
+#include "libkshark.h"
+#include "KsPlotTools.hpp"
+
+#define GRAPH_HEIGHT	40   // width of the graph in pixels
+#define GRAPH_H_MARGIN	50   // size of the white space surrounding the graph
+#define WINDOW_WIDTH	1200  // width of the screen window in pixels
+#define WINDOW_HEIGHT	720  // height of the scrren window in pixels
+
+using namespace std;
+
+kshark_trace_histo histo_m;
+vector<KsPlot::Graph *> graphs;
+int *stream_ids;
+
+void calib(kshark_entry *e, int64_t *atgv) {
+	e->ts += atgv[0];
+}
+
+void plot()
+{
+	KsPlot::Color::setRainbowFrequency(.9);
+	KsPlot::ColorTable pidColors = KsPlot::getTaskColorTable();
+	vector<KsPlot::Graph *>::iterator it;
+	kshark_context *kshark_ctx(nullptr);
+	struct kshark_data_stream *stream;
+	KsPlot::Graph *graph;
+	int base, nCPUs, sd;
+
+	if (!kshark_instance(&kshark_ctx))
+		return;
+
+	for (int d = 0; d < kshark_ctx->n_streams; ++d) {
+		sd = stream_ids[d];
+		stream = kshark_get_data_stream(kshark_ctx, sd);
+		nCPUs = tep_get_cpus(stream->pevent);
+		for (int cpu = 0; cpu < nCPUs; ++cpu) {
+// 			graph = new KsPlot::Graph(&histos[d], &colors);
+			graph = new KsPlot::Graph(&histo_m, &pidColors,
+							    &pidColors);
+
+			/* Set the dimensions of the Graph. */
+			graph->setHeight(GRAPH_HEIGHT);
+			graph->setHMargin(GRAPH_H_MARGIN);
+
+			/*
+			 * Set the Y coordinate of the Graph's base.
+			 * Remember that the "Y" coordinate is inverted.
+			 */
+			base = 1.7 * GRAPH_HEIGHT * (graphs.size() + 1);
+			graph->setBase(base);
+
+			graph->fillCPUGraph(sd, cpu);
+
+			/* Add the Graph. */
+			graphs.push_back(graph);
+		}
+	}
+
+	/* Clear the screen. */
+	glClear(GL_COLOR_BUFFER_BIT);
+
+	/* Draw all graphs. */
+	for (auto &g: graphs)
+		g->draw();
+
+	glFlush();
+}
+
+int main(int argc, char **argv)
+{
+	vector<kshark_entry **> data(argc - 1, nullptr);
+	kshark_entry ** data_m;
+	vector<size_t> nRows(argc - 1, 0);
+	kshark_context *kshark_ctx(nullptr);
+	int nBins;
+	size_t r, tot;
+	int64_t timeShift;
+
+	/* Create a new kshark session. */
+	if (!kshark_instance(&kshark_ctx))
+		return 1;
+
+	if (argc != 3)
+		return 1;
+
+	for (int i = 1; i < argc; ++i) {
+		if (kshark_open(kshark_ctx, argv[i]) < 0) {
+			cerr << "Unable to load file " << argv[i] << endl;
+			return 1;
+		}
+	}
+
+	stream_ids = kshark_all_streams(kshark_ctx);
+	for (int d = 0; d < kshark_ctx->n_streams; ++d) {
+		nRows[d] = kshark_load_data_entries(kshark_ctx,
+						    stream_ids[d],
+						    &data[d]);
+	}
+
+	timeShift = data[0][0]->ts - data[1][0]->ts;
+	tot = nRows[0] + nRows[1];
+	printf("%lu  %lu  t0 %lu\n",  data[0][0]->ts, data[1][0]->ts, timeShift);
+	data_m = kshark_data_merge(data[0], nRows[0],
+				   data[1], nRows[1],
+				   calib, &timeShift);
+
+	for (size_t i = 1; i < tot; ++i) {
+		if (data_m[i]->ts < data_m[i-1]->ts)
+			break;
+	}
+
+	nBins = WINDOW_WIDTH - 2 * GRAPH_H_MARGIN;
+
+	ksmodel_init(&histo_m);
+	ksmodel_set_bining(&histo_m, nBins, data_m[0]->ts,
+					    data_m[tot - 1]->ts);
+
+	/* Fill the model with data and calculate its state. */
+	ksmodel_fill(&histo_m, data_m, tot);
+
+	glutInit(&argc, argv);
+	ksplot_make_scene(WINDOW_WIDTH, WINDOW_HEIGHT);
+	ksplot_init_opengl(1);
+
+	/* Display graphs. */
+	glutDisplayFunc(plot);
+	glutMainLoop();
+
+	/* Free the memory. */
+	free(stream_ids);
+
+	for (size_t d = 0; d < data.size(); ++d) {
+		for (r = 0; r < nRows[d]; ++r)
+			free(data[d][r]);
+
+		free(data[d]);
+	}
+
+	free(data_m);
+
+	/* Close the session. */
+	kshark_free(kshark_ctx);
+
+	return 0;
+}