blob: 4804f813554a99c037e5bc97881139ab45aaec5d [file] [log] [blame]
Chris Wilsonb98bade2013-08-20 21:39:27 +01001/*
2 * Copyright © 2013 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 *
23 */
24
Chris Wilsonf9a50de2013-08-17 11:12:07 +010025#include <sys/types.h>
26#include <sys/mman.h>
27#include <cairo.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <stdbool.h>
31#include <string.h>
32#include <unistd.h>
Chris Wilsoncbbd55a2013-08-17 20:04:11 +010033#include <fcntl.h>
Chris Wilsonf9a50de2013-08-17 11:12:07 +010034#include <errno.h>
Chris Wilson5cb8c772013-08-20 19:24:33 +010035#include <signal.h>
Chris Wilson7c52a3c2013-08-22 15:07:48 +010036#include <getopt.h>
Chris Wilson9bebbbc2013-08-28 12:37:14 +010037#include <time.h>
Chris Wilson44d444a2015-06-24 17:01:21 +010038#include <locale.h>
Chris Wilsonf9a50de2013-08-17 11:12:07 +010039
40#include "overlay.h"
Chris Wilsonf71d7ae2013-08-19 22:26:01 +010041#include "chart.h"
Chris Wilson7c52a3c2013-08-22 15:07:48 +010042#include "config.h"
Chris Wilson6a64ee92013-08-18 15:56:22 +010043#include "cpu-top.h"
Chris Wilsonf71d7ae2013-08-19 22:26:01 +010044#include "debugfs.h"
Chris Wilsonc9f01732013-08-25 20:13:31 +010045#include "gem-interrupts.h"
Chris Wilsonde2c97b2013-08-18 16:42:25 +010046#include "gem-objects.h"
47#include "gpu-freq.h"
Chris Wilsonf9a50de2013-08-17 11:12:07 +010048#include "gpu-top.h"
Chris Wilsoncc45a9a2013-08-17 17:38:37 +010049#include "gpu-perf.h"
Chris Wilson5c81cda2013-08-20 10:04:23 +010050#include "power.h"
Chris Wilsonbaa5be02013-08-20 09:27:34 +010051#include "rc6.h"
Chris Wilsonf9a50de2013-08-17 11:12:07 +010052
Chris Wilsonc8885072013-08-20 11:08:13 +010053#define is_power_of_two(x) (((x) & ((x)-1)) == 0)
54
Chris Wilson04a4fae2013-08-26 14:45:26 +010055#define PAD 10
56#define HALF_PAD 5
57#define SIZE_PAD (PAD + HALF_PAD)
58
Chris Wilson59f13442013-08-29 13:33:21 +010059#define IDLE_TIME 30
60
Chris Wilsonf9a50de2013-08-17 11:12:07 +010061const cairo_user_data_key_t overlay_key;
62
63static void overlay_show(cairo_surface_t *surface)
64{
65 struct overlay *overlay;
66
67 overlay = cairo_surface_get_user_data(surface, &overlay_key);
68 if (overlay == NULL)
69 return;
70
71 overlay->show(overlay);
72}
73
74#if 0
75static void overlay_position(cairo_surface_t *surface, enum position p)
76{
77 struct overlay *overlay;
78
79 overlay = cairo_surface_get_user_data(surface, &overlay_key);
80 if (overlay == NULL)
81 return;
82
83 overlay->position(overlay, p);
84}
85
86static void overlay_hide(cairo_surface_t *surface)
87{
88 struct overlay *overlay;
89
90 overlay = cairo_surface_get_user_data(surface, &overlay_key);
91 if (overlay == NULL)
92 return;
93
94 overlay->hide(overlay);
95}
96#endif
97
98struct overlay_gpu_top {
99 struct gpu_top gpu_top;
Chris Wilson6a64ee92013-08-18 15:56:22 +0100100 struct cpu_top cpu_top;
Chris Wilson06c0cc02013-08-17 12:32:17 +0100101 struct chart busy[MAX_RINGS];
102 struct chart wait[MAX_RINGS];
Chris Wilson6a64ee92013-08-18 15:56:22 +0100103 struct chart cpu;
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100104};
105
Chris Wilson74032f42013-08-18 18:40:03 +0100106struct overlay_gpu_perf {
107 struct gpu_perf gpu_perf;
Chris Wilson474ce532013-08-29 12:01:38 +0100108 time_t show_ctx;
Chris Wilson2f297ed2013-08-29 13:19:29 +0100109 time_t show_flips;
Chris Wilson74032f42013-08-18 18:40:03 +0100110};
111
112struct overlay_gpu_freq {
113 struct gpu_freq gpu_freq;
Chris Wilsonbaa5be02013-08-20 09:27:34 +0100114 struct rc6 rc6;
Chris Wilsonc9f01732013-08-25 20:13:31 +0100115 struct gem_interrupts irqs;
Chris Wilson5c81cda2013-08-20 10:04:23 +0100116 struct power power;
Chris Wilson74032f42013-08-18 18:40:03 +0100117 struct chart current;
118 struct chart request;
Chris Wilson5c81cda2013-08-20 10:04:23 +0100119 struct chart power_chart;
Chris Wilsone34fab52013-08-21 11:06:51 +0100120 double power_max;
Chris Wilson74032f42013-08-18 18:40:03 +0100121};
122
123struct overlay_gem_objects {
124 struct gem_objects gem_objects;
125 struct chart aperture;
126 struct chart gtt;
127 int error;
128};
129
130struct overlay_context {
131 cairo_surface_t *surface;
132 cairo_t *cr;
133 int width, height;
Chris Wilson74032f42013-08-18 18:40:03 +0100134
Chris Wilson474ce532013-08-29 12:01:38 +0100135 time_t time;
136
Chris Wilson74032f42013-08-18 18:40:03 +0100137 struct overlay_gpu_top gpu_top;
138 struct overlay_gpu_perf gpu_perf;
139 struct overlay_gpu_freq gpu_freq;
140 struct overlay_gem_objects gem_objects;
141};
142
143static void init_gpu_top(struct overlay_context *ctx,
144 struct overlay_gpu_top *gt)
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100145{
146 const double rgba[][4] = {
Chris Wilsoncc9de392013-08-17 20:32:58 +0100147 { 1, 0.25, 0.25, 1 },
148 { 0.25, 1, 0.25, 1 },
149 { 0.25, 0.25, 1, 1 },
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100150 { 1, 1, 1, 1 },
151 };
152 int n;
153
Chris Wilsonc6b26c52013-08-27 17:40:45 +0100154 cpu_top_init(&gt->cpu_top);
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100155 gpu_top_init(&gt->gpu_top);
Chris Wilson6a64ee92013-08-18 15:56:22 +0100156
157 chart_init(&gt->cpu, "CPU", 120);
Chris Wilson04a4fae2013-08-26 14:45:26 +0100158 chart_set_position(&gt->cpu, PAD, PAD);
159 chart_set_size(&gt->cpu, ctx->width/2 - SIZE_PAD, ctx->height/2 - SIZE_PAD);
Chris Wilson6a64ee92013-08-18 15:56:22 +0100160 chart_set_stroke_rgba(&gt->cpu, 0.75, 0.25, 0.75, 1.);
161 chart_set_mode(&gt->cpu, CHART_STROKE);
162 chart_set_range(&gt->cpu, 0, 100);
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100163
164 for (n = 0; n < gt->gpu_top.num_rings; n++) {
Chris Wilson06c0cc02013-08-17 12:32:17 +0100165 chart_init(&gt->busy[n],
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100166 gt->gpu_top.ring[n].name,
167 120);
Chris Wilson04a4fae2013-08-26 14:45:26 +0100168 chart_set_position(&gt->busy[n], PAD, PAD);
169 chart_set_size(&gt->busy[n], ctx->width/2 - SIZE_PAD, ctx->height/2 - SIZE_PAD);
Chris Wilson06c0cc02013-08-17 12:32:17 +0100170 chart_set_stroke_rgba(&gt->busy[n],
171 rgba[n][0], rgba[n][1], rgba[n][2], rgba[n][3]);
172 chart_set_mode(&gt->busy[n], CHART_STROKE);
173 chart_set_range(&gt->busy[n], 0, 100);
174 }
175
176 for (n = 0; n < gt->gpu_top.num_rings; n++) {
177 chart_init(&gt->wait[n],
178 gt->gpu_top.ring[n].name,
179 120);
Chris Wilson04a4fae2013-08-26 14:45:26 +0100180 chart_set_position(&gt->wait[n], PAD, PAD);
181 chart_set_size(&gt->wait[n], ctx->width/2 - SIZE_PAD, ctx->height/2 - SIZE_PAD);
Chris Wilson06c0cc02013-08-17 12:32:17 +0100182 chart_set_fill_rgba(&gt->wait[n],
183 rgba[n][0], rgba[n][1], rgba[n][2], rgba[n][3] * 0.70);
184 chart_set_mode(&gt->wait[n], CHART_FILL);
185 chart_set_range(&gt->wait[n], 0, 100);
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100186 }
187}
188
Chris Wilsoncbbd55a2013-08-17 20:04:11 +0100189static void show_gpu_top(struct overlay_context *ctx, struct overlay_gpu_top *gt)
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100190{
Chris Wilsone34fab52013-08-21 11:06:51 +0100191 int y, y1, y2, n, update, len;
192 cairo_pattern_t *linear;
Chris Wilson6a64ee92013-08-18 15:56:22 +0100193 char txt[160];
Chris Wilsona18023f2013-08-27 23:51:32 +0100194 int rewind;
195 int do_rewind;
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100196
197 update = gpu_top_update(&gt->gpu_top);
Chris Wilson6a64ee92013-08-18 15:56:22 +0100198
Chris Wilson04a4fae2013-08-26 14:45:26 +0100199 cairo_rectangle(ctx->cr, PAD-.5, PAD-.5, ctx->width/2-SIZE_PAD+1, ctx->height/2-SIZE_PAD+1);
Chris Wilsondb35f8c2013-08-21 13:36:29 +0100200 cairo_set_source_rgb(ctx->cr, .15, .15, .15);
201 cairo_set_line_width(ctx->cr, 1);
202 cairo_stroke(ctx->cr);
203
Chris Wilson6a64ee92013-08-18 15:56:22 +0100204 if (update && cpu_top_update(&gt->cpu_top) == 0)
205 chart_add_sample(&gt->cpu, gt->cpu_top.busy);
Chris Wilson6a64ee92013-08-18 15:56:22 +0100206
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100207 for (n = 0; n < gt->gpu_top.num_rings; n++) {
208 if (update)
Chris Wilson06c0cc02013-08-17 12:32:17 +0100209 chart_add_sample(&gt->wait[n],
210 gt->gpu_top.ring[n].u.u.wait + gt->gpu_top.ring[n].u.u.sema);
Chris Wilsoncbbd55a2013-08-17 20:04:11 +0100211 chart_draw(&gt->wait[n], ctx->cr);
Chris Wilson06c0cc02013-08-17 12:32:17 +0100212 }
213 for (n = 0; n < gt->gpu_top.num_rings; n++) {
214 if (update)
215 chart_add_sample(&gt->busy[n],
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100216 gt->gpu_top.ring[n].u.u.busy);
Chris Wilsoncbbd55a2013-08-17 20:04:11 +0100217 chart_draw(&gt->busy[n], ctx->cr);
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100218 }
Chris Wilson20a25f52013-08-24 12:59:31 +0100219 chart_draw(&gt->cpu, ctx->cr);
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100220
Chris Wilson04a4fae2013-08-26 14:45:26 +0100221 y1 = PAD - 2;
Chris Wilsone34fab52013-08-21 11:06:51 +0100222 y2 = y1 + (gt->gpu_top.num_rings+1) * 14 + 4;
223
Chris Wilson04a4fae2013-08-26 14:45:26 +0100224 cairo_rectangle(ctx->cr, PAD, y1, ctx->width/2-SIZE_PAD, y2-y1);
225 linear = cairo_pattern_create_linear(PAD, 0, PAD+ctx->width/2-SIZE_PAD, 0);
Chris Wilsone34fab52013-08-21 11:06:51 +0100226 cairo_pattern_add_color_stop_rgba(linear, 0, 0, 0, 0, .5);
227 cairo_pattern_add_color_stop_rgba(linear, 1, 0, 0, 0, .0);
228 cairo_set_source(ctx->cr, linear);
229 cairo_pattern_destroy(linear);
230 cairo_fill(ctx->cr);
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100231
Chris Wilson04a4fae2013-08-26 14:45:26 +0100232 y = PAD + 12 - 2;
Chris Wilson6a64ee92013-08-18 15:56:22 +0100233 cairo_set_source_rgba(ctx->cr, 0.75, 0.25, 0.75, 1.);
Chris Wilson04a4fae2013-08-26 14:45:26 +0100234 cairo_move_to(ctx->cr, PAD, y);
Chris Wilsona18023f2013-08-27 23:51:32 +0100235 rewind = len = sprintf(txt, "CPU: %3d%% busy", gt->cpu_top.busy * gt->cpu_top.nr_cpu);
236 do_rewind = 1;
237 len += sprintf(txt + len, " (");
238 if (gt->cpu_top.nr_cpu > 1) {
239 len += sprintf(txt + len, "%s%d cores", do_rewind ? "" : ", ", gt->cpu_top.nr_cpu);
240 do_rewind = 0;
241 }
242 if (gt->cpu_top.nr_running) {
243 len += sprintf(txt + len, "%s%d processes", do_rewind ? "" : ", ", gt->cpu_top.nr_running);
244 do_rewind = 0;
245 }
246 sprintf(txt + len, ")");
247 if (do_rewind)
248 txt[rewind] = '\0';
Chris Wilson6a64ee92013-08-18 15:56:22 +0100249 cairo_show_text(ctx->cr, txt);
250 y += 14;
251
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100252 for (n = 0; n < gt->gpu_top.num_rings; n++) {
Chris Wilsoncc9de392013-08-17 20:32:58 +0100253 struct chart *c =&gt->busy[n];
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100254
Chris Wilson396fa1b2013-08-27 12:54:37 +0100255 len = sprintf(txt, "%s: %3d%% busy",
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100256 gt->gpu_top.ring[n].name,
257 gt->gpu_top.ring[n].u.u.busy);
258 if (gt->gpu_top.ring[n].u.u.wait)
259 len += sprintf(txt + len, ", %d%% wait",
260 gt->gpu_top.ring[n].u.u.wait);
261 if (gt->gpu_top.ring[n].u.u.sema)
262 len += sprintf(txt + len, ", %d%% sema",
263 gt->gpu_top.ring[n].u.u.sema);
264
Chris Wilsoncc9de392013-08-17 20:32:58 +0100265 cairo_set_source_rgba(ctx->cr,
266 c->stroke_rgb[0],
267 c->stroke_rgb[1],
268 c->stroke_rgb[2],
269 c->stroke_rgb[3]);
Chris Wilson04a4fae2013-08-26 14:45:26 +0100270 cairo_move_to(ctx->cr, PAD, y);
Chris Wilsoncbbd55a2013-08-17 20:04:11 +0100271 cairo_show_text(ctx->cr, txt);
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100272 y += 14;
273 }
274}
275
Chris Wilson74032f42013-08-18 18:40:03 +0100276static void init_gpu_perf(struct overlay_context *ctx,
277 struct overlay_gpu_perf *gp)
Chris Wilsoncc45a9a2013-08-17 17:38:37 +0100278{
279 gpu_perf_init(&gp->gpu_perf, 0);
Chris Wilson474ce532013-08-29 12:01:38 +0100280
281 gp->show_ctx = 0;
Chris Wilson2f297ed2013-08-29 13:19:29 +0100282 gp->show_flips = 0;
Chris Wilsoncc45a9a2013-08-17 17:38:37 +0100283}
284
Chris Wilsoncbbd55a2013-08-17 20:04:11 +0100285static char *get_comm(pid_t pid, char *comm, int len)
Chris Wilsoncc45a9a2013-08-17 17:38:37 +0100286{
Chris Wilsoncbbd55a2013-08-17 20:04:11 +0100287 char filename[1024];
288 int fd;
289
290 *comm = '\0';
291 snprintf(filename, sizeof(filename), "/proc/%d/comm", pid);
292
293 fd = open(filename, 0);
294 if (fd >= 0) {
Chris Wilsonbaa5be02013-08-20 09:27:34 +0100295 len = read(fd, comm, len);
Chris Wilsoncbbd55a2013-08-17 20:04:11 +0100296 if (len >= 0)
297 comm[len-1] = '\0';
298 close(fd);
299 }
300
301 return comm;
302}
303
304static void show_gpu_perf(struct overlay_context *ctx, struct overlay_gpu_perf *gp)
305{
Chris Wilsoncc9de392013-08-17 20:32:58 +0100306 static int last_color;
307 const double rgba[][4] = {
308 { 1, 0.25, 0.25, 1 },
309 { 0.25, 1, 0.25, 1 },
310 { 0.25, 0.25, 1, 1 },
311 { 1, 1, 1, 1 },
312 };
Chris Wilsoncbbd55a2013-08-17 20:04:11 +0100313 struct gpu_perf_comm *comm, **prev;
314 const char *ring_name[] = {
Chris Wilson908df372013-08-26 14:11:27 +0100315 "R",
Chris Wilson908df372013-08-26 14:11:27 +0100316 "B",
Chris Wilsonef430bd2017-05-10 14:09:16 +0100317 "V0",
318 "V1",
Chris Wilsoncbbd55a2013-08-17 20:04:11 +0100319 };
Chris Wilsoncc9de392013-08-17 20:32:58 +0100320 double range[2];
Chris Wilsoncc45a9a2013-08-17 17:38:37 +0100321 char buf[1024];
Chris Wilsone34fab52013-08-21 11:06:51 +0100322 cairo_pattern_t *linear;
323 int x, y, y1, y2, n;
Chris Wilson474ce532013-08-29 12:01:38 +0100324 int has_ctx = 0;
Chris Wilson2f297ed2013-08-29 13:19:29 +0100325 int has_flips = 0;
Chris Wilson474ce532013-08-29 12:01:38 +0100326
327 gpu_perf_update(&gp->gpu_perf);
328
Chris Wilson2f297ed2013-08-29 13:19:29 +0100329 for (n = 0; n < 4; n++) {
330 if (gp->gpu_perf.ctx_switch[n])
331 has_ctx = n + 1;
332 if (gp->gpu_perf.flip_complete[n])
333 has_flips = n + 1;
Chris Wilson474ce532013-08-29 12:01:38 +0100334 }
Chris Wilsoncc45a9a2013-08-17 17:38:37 +0100335
Chris Wilson04a4fae2013-08-26 14:45:26 +0100336 cairo_rectangle(ctx->cr, ctx->width/2+HALF_PAD-.5, PAD-.5, ctx->width/2-SIZE_PAD+1, ctx->height/2-SIZE_PAD+1);
Chris Wilson18478692013-08-22 10:59:58 +0000337 cairo_set_source_rgb(ctx->cr, .15, .15, .15);
338 cairo_set_line_width(ctx->cr, 1);
339 cairo_stroke(ctx->cr);
340
341 if (gp->gpu_perf.error) {
342 cairo_text_extents_t extents;
343 cairo_text_extents(ctx->cr, gp->gpu_perf.error, &extents);
344 cairo_move_to(ctx->cr,
Chris Wilson04a4fae2013-08-26 14:45:26 +0100345 ctx->width/2+HALF_PAD + (ctx->width/2-SIZE_PAD - extents.width)/2.,
346 PAD + (ctx->height/2-SIZE_PAD + extents.height)/2.);
Chris Wilson18478692013-08-22 10:59:58 +0000347 cairo_show_text(ctx->cr, gp->gpu_perf.error);
348 return;
349 }
350
Chris Wilson59f13442013-08-29 13:33:21 +0100351 if (gp->gpu_perf.comm == NULL && (has_ctx|has_flips) == 0) {
Chris Wilson2b961d92013-08-29 13:31:24 +0100352 cairo_text_extents_t extents;
353 cairo_text_extents(ctx->cr, gp->gpu_perf.error, &extents);
354 cairo_move_to(ctx->cr,
355 ctx->width/2+HALF_PAD + (ctx->width/2-SIZE_PAD - extents.width)/2.,
356 PAD + (ctx->height/2-SIZE_PAD + extents.height)/2.);
357 cairo_show_text(ctx->cr, "idle");
358 return;
359 }
360
Chris Wilson04a4fae2013-08-26 14:45:26 +0100361 y = PAD + 12 - 2;
362 x = ctx->width/2 + HALF_PAD;
Chris Wilsondb35f8c2013-08-21 13:36:29 +0100363
Chris Wilsoncc9de392013-08-17 20:32:58 +0100364 for (comm = gp->gpu_perf.comm; comm; comm = comm->next) {
365 int total;
366
Chris Wilsoneb799b22014-12-21 13:53:27 +0000367 if (comm->name[0] == '\0')
368 continue;
369
370 if (strncmp(comm->name, "kworker", 7) == 0)
371 continue;
372
Chris Wilsoncc9de392013-08-17 20:32:58 +0100373 if (comm->user_data == NULL) {
374 comm->user_data = malloc(sizeof(struct chart));
375 if (comm->user_data == NULL)
376 continue;
377
378 chart_init(comm->user_data, comm->name, 120);
Chris Wilson04a4fae2013-08-26 14:45:26 +0100379 chart_set_position(comm->user_data, ctx->width/2+HALF_PAD, PAD);
380 chart_set_size(comm->user_data, ctx->width/2-SIZE_PAD, ctx->height/2 - SIZE_PAD);
Chris Wilsoncc9de392013-08-17 20:32:58 +0100381 chart_set_mode(comm->user_data, CHART_STROKE);
382 chart_set_stroke_rgba(comm->user_data,
383 rgba[last_color][0],
384 rgba[last_color][1],
385 rgba[last_color][2],
386 rgba[last_color][3]);
Chris Wilson00282ed2013-08-19 23:29:08 +0100387 last_color = (last_color + 1) % 4;
Chris Wilsoncc9de392013-08-17 20:32:58 +0100388 chart_set_stroke_width(comm->user_data, 1);
389 }
390
391 total = 0;
392 for (n = 0; n < 3; n++)
393 total += comm->nr_requests[n];
394 chart_add_sample(comm->user_data, total);
395 }
396
397 range[0] = range[1] = 0;
Chris Wilsoneb799b22014-12-21 13:53:27 +0000398 for (comm = gp->gpu_perf.comm; comm; comm = comm->next) {
399 if (comm->user_data == NULL)
400 continue;
401
Chris Wilsoncc9de392013-08-17 20:32:58 +0100402 chart_get_range(comm->user_data, range);
Chris Wilsoneb799b22014-12-21 13:53:27 +0000403 }
Chris Wilsone34fab52013-08-21 11:06:51 +0100404
405 y2 = y1 = y;
Chris Wilsoncc9de392013-08-17 20:32:58 +0100406 for (comm = gp->gpu_perf.comm; comm; comm = comm->next) {
Chris Wilsoneb799b22014-12-21 13:53:27 +0000407 if (comm->user_data == NULL)
408 continue;
409
Chris Wilsoncc9de392013-08-17 20:32:58 +0100410 chart_set_range(comm->user_data, range[0], range[1]);
411 chart_draw(comm->user_data, ctx->cr);
Chris Wilsone34fab52013-08-21 11:06:51 +0100412 y2 += 14;
Chris Wilsoncc9de392013-08-17 20:32:58 +0100413 }
Chris Wilson2f297ed2013-08-29 13:19:29 +0100414 if (has_flips || gp->show_flips)
415 y2 += 14;
Chris Wilson474ce532013-08-29 12:01:38 +0100416 if (has_ctx || gp->show_ctx)
417 y2 += 14;
Chris Wilsone34fab52013-08-21 11:06:51 +0100418 y1 += -12 - 2;
Chris Wilson2f297ed2013-08-29 13:19:29 +0100419 y2 += -14 + 4;
Chris Wilsone34fab52013-08-21 11:06:51 +0100420
Chris Wilson04a4fae2013-08-26 14:45:26 +0100421 cairo_rectangle(ctx->cr, x, y1, ctx->width/2-SIZE_PAD, y2-y1);
422 linear = cairo_pattern_create_linear(x, 0, x + ctx->width/2-SIZE_PAD, 0);
Chris Wilsone34fab52013-08-21 11:06:51 +0100423 cairo_pattern_add_color_stop_rgba(linear, 0, 0, 0, 0, .5);
424 cairo_pattern_add_color_stop_rgba(linear, 1, 0, 0, 0, .0);
425 cairo_set_source(ctx->cr, linear);
426 cairo_pattern_destroy(linear);
427 cairo_fill(ctx->cr);
Chris Wilsoncc9de392013-08-17 20:32:58 +0100428
Chris Wilsoncbbd55a2013-08-17 20:04:11 +0100429 for (prev = &gp->gpu_perf.comm; (comm = *prev) != NULL; ) {
Chris Wilson908df372013-08-26 14:11:27 +0100430 int need_comma = 0, len;
431
Chris Wilsoneb799b22014-12-21 13:53:27 +0000432 if (comm->user_data == NULL)
Chris Wilson908df372013-08-26 14:11:27 +0100433 goto skip_comm;
434
435 len = sprintf(buf, "%s:", comm->name);
Chris Wilsonef430bd2017-05-10 14:09:16 +0100436 for (n = 0; n < sizeof(ring_name)/sizeof(ring_name[0]); n++) {
Chris Wilson908df372013-08-26 14:11:27 +0100437 if (comm->nr_requests[n] == 0)
438 continue;
439 len += sprintf(buf + len, "%s %d%s", need_comma ? "," : "", comm->nr_requests[n], ring_name[n]);
440 need_comma = true;
Chris Wilson2b961d92013-08-29 13:31:24 +0100441 comm->show = ctx->time;
Chris Wilson908df372013-08-26 14:11:27 +0100442 }
443 if (comm->wait_time) {
444 if (comm->wait_time > 1000*1000) {
445 len += sprintf(buf + len, "%s %.1fms waits",
446 need_comma ? "," : "",
447 comm->wait_time / (1000*1000.));
448 } else if (comm->wait_time > 100) {
449 len += sprintf(buf + len, "%s %.1fus waits",
450 need_comma ? "," : "",
451 comm->wait_time / 1000.);
452 } else {
453 len += sprintf(buf, "%s %.0fns waits",
454 need_comma ? "," : "",
455 (double)comm->wait_time);
456 }
457 need_comma = true;
458 comm->wait_time = 0;
Chris Wilson2b961d92013-08-29 13:31:24 +0100459 comm->show = ctx->time;
Chris Wilson908df372013-08-26 14:11:27 +0100460 }
461 if (comm->nr_sema) {
462 len += sprintf(buf + len, "%s %d syncs",
463 need_comma ? "," : "",
464 comm->nr_sema);
465 need_comma = true;
466 comm->nr_sema = 0;
Chris Wilson2b961d92013-08-29 13:31:24 +0100467 comm->show = ctx->time;
Chris Wilson908df372013-08-26 14:11:27 +0100468 }
Chris Wilsoneed59ea2013-08-17 21:14:10 +0100469
Chris Wilsoncc9de392013-08-17 20:32:58 +0100470 if (comm->user_data) {
471 struct chart *c = comm->user_data;
472 cairo_set_source_rgba(ctx->cr,
473 c->stroke_rgb[0],
474 c->stroke_rgb[1],
475 c->stroke_rgb[2],
476 c->stroke_rgb[3]);
477 } else
478 cairo_set_source_rgba(ctx->cr, 1, 1, 1, 1);
Chris Wilson6a382002013-08-18 18:45:14 +0100479 cairo_move_to(ctx->cr, x, y);
Chris Wilsoncbbd55a2013-08-17 20:04:11 +0100480 cairo_show_text(ctx->cr, buf);
Chris Wilsoncbbd55a2013-08-17 20:04:11 +0100481 y += 14;
482
Chris Wilson908df372013-08-26 14:11:27 +0100483skip_comm:
Chris Wilsoncbbd55a2013-08-17 20:04:11 +0100484 memset(comm->nr_requests, 0, sizeof(comm->nr_requests));
Chris Wilsoneb799b22014-12-21 13:53:27 +0000485 if (!comm->active &&
486 (comm->show < ctx->time - IDLE_TIME ||
487 strcmp(comm->name, get_comm(comm->pid, buf, sizeof(buf))))) {
Chris Wilsoncbbd55a2013-08-17 20:04:11 +0100488 *prev = comm->next;
Chris Wilsoncc9de392013-08-17 20:32:58 +0100489 if (comm->user_data) {
490 chart_fini(comm->user_data);
491 free(comm->user_data);
492 }
Chris Wilsoncbbd55a2013-08-17 20:04:11 +0100493 free(comm);
494 } else
495 prev = &comm->next;
496 }
Chris Wilsoncc45a9a2013-08-17 17:38:37 +0100497
Chris Wilsoncc9de392013-08-17 20:32:58 +0100498 cairo_set_source_rgba(ctx->cr, 1, 1, 1, 1);
Chris Wilson6a382002013-08-18 18:45:14 +0100499 cairo_move_to(ctx->cr, x, y);
Chris Wilson2f297ed2013-08-29 13:19:29 +0100500 if (has_flips) {
501 int len = sprintf(buf, "Flips:");
502 for (n = 0; n < has_flips; n++)
503 len += sprintf(buf + len, "%s %d",
504 n ? "," : "",
505 gp->gpu_perf.flip_complete[n]);
506 memset(gp->gpu_perf.flip_complete, 0, sizeof(gp->gpu_perf.flip_complete));
507 gp->show_flips = ctx->time;
508
509 cairo_show_text(ctx->cr, buf);
510 y += 14;
511 } else if (gp->show_flips) {
512 cairo_show_text(ctx->cr, "Flips: 0");
Chris Wilson59f13442013-08-29 13:33:21 +0100513 if (ctx->time - gp->show_flips > IDLE_TIME)
Chris Wilson2f297ed2013-08-29 13:19:29 +0100514 gp->show_flips = 0;
515 y += 14;
516 }
Chris Wilson474ce532013-08-29 12:01:38 +0100517
518 cairo_set_source_rgba(ctx->cr, 1, 1, 1, 1);
519 cairo_move_to(ctx->cr, x, y);
520 if (has_ctx) {
521 int len = sprintf(buf, "Contexts:");
522 for (n = 0; n < has_ctx; n++)
523 len += sprintf(buf + len, "%s %d",
524 n ? "," : "",
525 gp->gpu_perf.ctx_switch[n]);
526
527 memset(gp->gpu_perf.ctx_switch, 0, sizeof(gp->gpu_perf.ctx_switch));
528 gp->show_ctx = ctx->time;
529
530 cairo_show_text(ctx->cr, buf);
531 y += 14;
532 } else if (gp->show_ctx) {
533 cairo_show_text(ctx->cr, "Contexts: 0");
534 y += 14;
Chris Wilson59f13442013-08-29 13:33:21 +0100535 if (ctx->time - gp->show_ctx > IDLE_TIME)
Chris Wilson474ce532013-08-29 12:01:38 +0100536 gp->show_ctx = 0;
537 }
Chris Wilsoncc45a9a2013-08-17 17:38:37 +0100538}
539
Chris Wilson74032f42013-08-18 18:40:03 +0100540static void init_gpu_freq(struct overlay_context *ctx,
541 struct overlay_gpu_freq *gf)
Chris Wilsonde2c97b2013-08-18 16:42:25 +0100542{
Chris Wilson5c81cda2013-08-20 10:04:23 +0100543 if (gpu_freq_init(&gf->gpu_freq) == 0) {
544 chart_init(&gf->current, "current", 120);
Chris Wilson04a4fae2013-08-26 14:45:26 +0100545 chart_set_position(&gf->current, PAD, ctx->height/2 + HALF_PAD);
546 chart_set_size(&gf->current, ctx->width/2 - SIZE_PAD, ctx->height/2 - SIZE_PAD);
Chris Wilson5c81cda2013-08-20 10:04:23 +0100547 chart_set_stroke_rgba(&gf->current, 0.75, 0.25, 0.50, 1.);
548 chart_set_mode(&gf->current, CHART_STROKE);
549 chart_set_smooth(&gf->current, CHART_LINE);
550 chart_set_range(&gf->current, 0, gf->gpu_freq.max);
551
552 chart_init(&gf->request, "request", 120);
Chris Wilson04a4fae2013-08-26 14:45:26 +0100553 chart_set_position(&gf->request, PAD, ctx->height/2 + HALF_PAD);
554 chart_set_size(&gf->request, ctx->width/2 - SIZE_PAD, ctx->height/2 - SIZE_PAD);
Chris Wilson5c81cda2013-08-20 10:04:23 +0100555 chart_set_fill_rgba(&gf->request, 0.25, 0.25, 0.50, 1.);
556 chart_set_mode(&gf->request, CHART_FILL);
557 chart_set_smooth(&gf->request, CHART_LINE);
558 chart_set_range(&gf->request, 0, gf->gpu_freq.max);
559 }
560
561 if (power_init(&gf->power) == 0) {
562 chart_init(&gf->power_chart, "power", 120);
Chris Wilson04a4fae2013-08-26 14:45:26 +0100563 chart_set_position(&gf->power_chart, PAD, ctx->height/2 + HALF_PAD);
564 chart_set_size(&gf->power_chart, ctx->width/2 - SIZE_PAD, ctx->height/2 - SIZE_PAD);
Chris Wilson5c81cda2013-08-20 10:04:23 +0100565 chart_set_stroke_rgba(&gf->power_chart, 0.45, 0.55, 0.45, 1.);
Chris Wilsone34fab52013-08-21 11:06:51 +0100566 gf->power_max = 0;
Chris Wilson5c81cda2013-08-20 10:04:23 +0100567 }
Chris Wilsonde2c97b2013-08-18 16:42:25 +0100568
Chris Wilsonbaa5be02013-08-20 09:27:34 +0100569 rc6_init(&gf->rc6);
Chris Wilsonc9f01732013-08-25 20:13:31 +0100570 gem_interrupts_init(&gf->irqs);
Chris Wilsonde2c97b2013-08-18 16:42:25 +0100571}
572
573static void show_gpu_freq(struct overlay_context *ctx, struct overlay_gpu_freq *gf)
574{
575 char buf[160];
Chris Wilsone34fab52013-08-21 11:06:51 +0100576 int y1, y2, y, len;
Chris Wilsonde2c97b2013-08-18 16:42:25 +0100577
Chris Wilsone34fab52013-08-21 11:06:51 +0100578 int has_freq = gpu_freq_update(&gf->gpu_freq) == 0;
579 int has_rc6 = rc6_update(&gf->rc6) == 0;
580 int has_power = power_update(&gf->power) == 0;
Chris Wilsonc9f01732013-08-25 20:13:31 +0100581 int has_irqs = gem_interrupts_update(&gf->irqs) == 0;
Chris Wilsone34fab52013-08-21 11:06:51 +0100582 cairo_pattern_t *linear;
Chris Wilsonde2c97b2013-08-18 16:42:25 +0100583
Chris Wilson04a4fae2013-08-26 14:45:26 +0100584 cairo_rectangle(ctx->cr, PAD-.5, ctx->height/2+HALF_PAD-.5, ctx->width/2-SIZE_PAD+1, ctx->height/2-SIZE_PAD+1);
Chris Wilsondb35f8c2013-08-21 13:36:29 +0100585 cairo_set_source_rgb(ctx->cr, .15, .15, .15);
586 cairo_set_line_width(ctx->cr, 1);
587 cairo_stroke(ctx->cr);
588
Chris Wilson18478692013-08-22 10:59:58 +0000589 if (gf->gpu_freq.error) {
590 const char *txt = "GPU frequency not found in debugfs";
591 cairo_text_extents_t extents;
592 cairo_text_extents(ctx->cr, txt, &extents);
593 cairo_move_to(ctx->cr,
Chris Wilson04a4fae2013-08-26 14:45:26 +0100594 PAD + (ctx->width/2-SIZE_PAD - extents.width)/2.,
595 ctx->height/2+HALF_PAD + (ctx->height/2-SIZE_PAD + extents.height)/2.);
Chris Wilson18478692013-08-22 10:59:58 +0000596 cairo_show_text(ctx->cr, txt);
597 return;
598 }
599
Chris Wilsone34fab52013-08-21 11:06:51 +0100600 if (has_freq) {
Chris Wilson5c81cda2013-08-20 10:04:23 +0100601 if (gf->gpu_freq.current)
602 chart_add_sample(&gf->current, gf->gpu_freq.current);
603 if (gf->gpu_freq.request)
604 chart_add_sample(&gf->request, gf->gpu_freq.request);
605
606 chart_draw(&gf->request, ctx->cr);
607 chart_draw(&gf->current, ctx->cr);
Chris Wilsone34fab52013-08-21 11:06:51 +0100608 }
Chris Wilson5c81cda2013-08-20 10:04:23 +0100609
Chris Wilsone34fab52013-08-21 11:06:51 +0100610 if (has_power) {
611 chart_add_sample(&gf->power_chart, gf->power.power_mW);
612 if (gf->power.new_sample) {
613 if (gf->power.power_mW > gf->power_max)
614 gf->power_max = gf->power.power_mW;
615 chart_set_range(&gf->power_chart, 0, gf->power_max);
616 gf->power.new_sample = 0;
617 }
618 chart_draw(&gf->power_chart, ctx->cr);
619 }
620
Chris Wilson04a4fae2013-08-26 14:45:26 +0100621 y = ctx->height/2 + HALF_PAD + 12 - 2;
Chris Wilsone34fab52013-08-21 11:06:51 +0100622
623 y1 = y2 = y;
624 if (has_freq) {
Chris Wilsonb1d2a782013-08-27 15:42:48 +0100625 y2 += 12;
626 y2 += 12;
Chris Wilsone34fab52013-08-21 11:06:51 +0100627 }
Chris Wilsonc9f01732013-08-25 20:13:31 +0100628 if (has_rc6)
Chris Wilsone34fab52013-08-21 11:06:51 +0100629 y2 += 14;
Chris Wilsonc9f01732013-08-25 20:13:31 +0100630 if (has_power)
Chris Wilsone34fab52013-08-21 11:06:51 +0100631 y2 += 14;
Chris Wilsonc9f01732013-08-25 20:13:31 +0100632 if (has_irqs)
633 y2 += 14;
Chris Wilsone34fab52013-08-21 11:06:51 +0100634 y1 += -12 - 2;
635 y2 += -14 + 4;
636
Chris Wilson04a4fae2013-08-26 14:45:26 +0100637 cairo_rectangle(ctx->cr, PAD, y1, ctx->width/2-SIZE_PAD, y2-y1);
638 linear = cairo_pattern_create_linear(PAD, 0, PAD+ctx->width/2-SIZE_PAD, 0);
Chris Wilsone34fab52013-08-21 11:06:51 +0100639 cairo_pattern_add_color_stop_rgba(linear, 0, 0, 0, 0, .5);
640 cairo_pattern_add_color_stop_rgba(linear, 1, 0, 0, 0, .0);
641 cairo_set_source(ctx->cr, linear);
642 cairo_pattern_destroy(linear);
643 cairo_fill(ctx->cr);
644
645 if (has_freq) {
Chris Wilson396fa1b2013-08-27 12:54:37 +0100646 cairo_text_extents_t extents;
647
Chris Wilson5c81cda2013-08-20 10:04:23 +0100648 len = sprintf(buf, "Frequency: %dMHz", gf->gpu_freq.current);
649 if (gf->gpu_freq.request)
Chris Wilson5c81cda2013-08-20 10:04:23 +0100650 cairo_set_source_rgba(ctx->cr, 1, 1, 1, 1);
Chris Wilson396fa1b2013-08-27 12:54:37 +0100651 sprintf(buf + len, " (requested %dMHz)", gf->gpu_freq.request);
Chris Wilson04a4fae2013-08-26 14:45:26 +0100652 cairo_move_to(ctx->cr, PAD, y);
Chris Wilson5c81cda2013-08-20 10:04:23 +0100653 cairo_show_text(ctx->cr, buf);
Chris Wilsonb1d2a782013-08-27 15:42:48 +0100654 y += 12;
Chris Wilson5c81cda2013-08-20 10:04:23 +0100655
Chris Wilson396fa1b2013-08-27 12:54:37 +0100656 cairo_text_extents(ctx->cr, "Frequency: ", &extents);
657
Chris Wilsonb1d2a782013-08-27 15:42:48 +0100658 cairo_set_font_size(ctx->cr, 8);
Chris Wilson396fa1b2013-08-27 12:54:37 +0100659 sprintf(buf, " min: %dMHz, max: %dMHz", gf->gpu_freq.min, gf->gpu_freq.max);
660 cairo_set_source_rgba(ctx->cr, .8, .8, .8, 1);
661 cairo_move_to(ctx->cr, PAD + extents.width, y);
Chris Wilson5c81cda2013-08-20 10:04:23 +0100662 cairo_show_text(ctx->cr, buf);
Chris Wilsonb1d2a782013-08-27 15:42:48 +0100663 cairo_set_font_size(ctx->cr, 10);
Chris Wilson396fa1b2013-08-27 12:54:37 +0100664 y += 12;
Chris Wilson5c81cda2013-08-20 10:04:23 +0100665 }
Chris Wilsonbaa5be02013-08-20 09:27:34 +0100666
Chris Wilsone34fab52013-08-21 11:06:51 +0100667 if (has_rc6) {
Chris Wilson396fa1b2013-08-27 12:54:37 +0100668 len = sprintf(buf, "RC6: %d%%", gf->rc6.rc6_combined);
669 cairo_set_source_rgba(ctx->cr, 1, 1, 1, 1);
Chris Wilson04a4fae2013-08-26 14:45:26 +0100670 cairo_move_to(ctx->cr, PAD, y);
Chris Wilson65d24812013-08-27 15:19:58 +0100671 if (gf->rc6.rc6_combined) {
Chris Wilson396fa1b2013-08-27 12:54:37 +0100672 int need_comma = 0;
Chris Wilson65d24812013-08-27 15:19:58 +0100673 int rewind = len;
Chris Wilson396fa1b2013-08-27 12:54:37 +0100674 len += sprintf(buf + len, " (");
Chris Wilson65d24812013-08-27 15:19:58 +0100675 if (gf->rc6.rc6) {
Chris Wilson396fa1b2013-08-27 12:54:37 +0100676 len += sprintf(buf + len, "%src6=%d%%",
677 need_comma ? ", " : "",
678 gf->rc6.rc6);
Chris Wilson65d24812013-08-27 15:19:58 +0100679 need_comma++;
Chris Wilsonc8885072013-08-20 11:08:13 +0100680 }
Chris Wilson65d24812013-08-27 15:19:58 +0100681 if (gf->rc6.rc6p) {
Chris Wilson396fa1b2013-08-27 12:54:37 +0100682 len += sprintf(buf + len, "%src6p=%d%%",
683 need_comma ? ", " : "",
684 gf->rc6.rc6p);
Chris Wilson65d24812013-08-27 15:19:58 +0100685 need_comma++;
Chris Wilsonc8885072013-08-20 11:08:13 +0100686 }
Chris Wilson65d24812013-08-27 15:19:58 +0100687 if (gf->rc6.rc6pp) {
Chris Wilson396fa1b2013-08-27 12:54:37 +0100688 len += sprintf(buf + len, "%src6pp=%d%%",
689 need_comma ? ", " : "",
690 gf->rc6.rc6pp);
Chris Wilson65d24812013-08-27 15:19:58 +0100691 need_comma++;
Chris Wilsonc8885072013-08-20 11:08:13 +0100692 }
Chris Wilson396fa1b2013-08-27 12:54:37 +0100693 sprintf(buf + len, ")");
Chris Wilson65d24812013-08-27 15:19:58 +0100694 if (need_comma <= 1)
695 buf[rewind] = '\0';
Chris Wilsonbaa5be02013-08-20 09:27:34 +0100696 }
Chris Wilson396fa1b2013-08-27 12:54:37 +0100697 cairo_show_text(ctx->cr, buf);
Chris Wilsonbaa5be02013-08-20 09:27:34 +0100698 y += 14;
699 }
Chris Wilson5c81cda2013-08-20 10:04:23 +0100700
Chris Wilsone34fab52013-08-21 11:06:51 +0100701 if (has_power) {
Chris Wilson5c81cda2013-08-20 10:04:23 +0100702 sprintf(buf, "Power: %llumW", (long long unsigned)gf->power.power_mW);
Chris Wilson87b66f42013-08-27 13:32:26 +0100703 cairo_set_source_rgba(ctx->cr, 1, 1, 1, 1);
Chris Wilson04a4fae2013-08-26 14:45:26 +0100704 cairo_move_to(ctx->cr, PAD, y);
Chris Wilson5c81cda2013-08-20 10:04:23 +0100705 cairo_show_text(ctx->cr, buf);
706 y += 14;
707 }
Chris Wilsonc9f01732013-08-25 20:13:31 +0100708
709 if (has_irqs) {
710 sprintf(buf, "Interrupts: %llu", (long long unsigned)gf->irqs.delta);
Chris Wilson87b66f42013-08-27 13:32:26 +0100711 cairo_set_source_rgba(ctx->cr, 1, 1, 1, 1);
Chris Wilson04a4fae2013-08-26 14:45:26 +0100712 cairo_move_to(ctx->cr, PAD, y);
Chris Wilsonc9f01732013-08-25 20:13:31 +0100713 cairo_show_text(ctx->cr, buf);
714 y += 14;
715 }
Chris Wilsonde2c97b2013-08-18 16:42:25 +0100716}
717
Chris Wilson74032f42013-08-18 18:40:03 +0100718static void init_gem_objects(struct overlay_context *ctx,
719 struct overlay_gem_objects *go)
Chris Wilsone1ed5602013-08-18 18:17:05 +0100720{
721 go->error = gem_objects_init(&go->gem_objects);
722 if (go->error)
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100723 return;
724
Chris Wilsone1ed5602013-08-18 18:17:05 +0100725 chart_init(&go->aperture, "aperture", 120);
Chris Wilson04a4fae2013-08-26 14:45:26 +0100726 chart_set_position(&go->aperture, ctx->width/2+HALF_PAD, ctx->height/2 + HALF_PAD);
727 chart_set_size(&go->aperture, ctx->width/2 - SIZE_PAD, ctx->height/2 - SIZE_PAD);
Chris Wilsone1ed5602013-08-18 18:17:05 +0100728 chart_set_stroke_rgba(&go->aperture, 0.75, 0.25, 0.50, 1.);
729 chart_set_mode(&go->aperture, CHART_STROKE);
730 chart_set_range(&go->aperture, 0, go->gem_objects.max_gtt);
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100731
Chris Wilsone1ed5602013-08-18 18:17:05 +0100732 chart_init(&go->gtt, "gtt", 120);
Chris Wilson04a4fae2013-08-26 14:45:26 +0100733 chart_set_position(&go->gtt, ctx->width/2+HALF_PAD, ctx->height/2 + HALF_PAD);
734 chart_set_size(&go->gtt, ctx->width/2 - SIZE_PAD, ctx->height/2 - SIZE_PAD);
Chris Wilson1c1a2792013-08-18 19:20:24 +0100735 chart_set_fill_rgba(&go->gtt, 0.25, 0.5, 0.5, 1.);
Chris Wilsone1ed5602013-08-18 18:17:05 +0100736 chart_set_mode(&go->gtt, CHART_FILL);
737 chart_set_range(&go->gtt, 0, go->gem_objects.max_gtt);
738}
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100739
Chris Wilsone1ed5602013-08-18 18:17:05 +0100740static void show_gem_objects(struct overlay_context *ctx, struct overlay_gem_objects *go)
741{
742 struct gem_objects_comm *comm;
Maarten Lankhorstf0bb1942017-11-21 14:26:07 +0100743 char buf[310];
Chris Wilsone34fab52013-08-21 11:06:51 +0100744 cairo_pattern_t *linear;
745 int x, y, y1, y2;
Chris Wilsone1ed5602013-08-18 18:17:05 +0100746
747 if (go->error == 0)
748 go->error = gem_objects_update(&go->gem_objects);
749 if (go->error)
750 return;
751
Chris Wilson04a4fae2013-08-26 14:45:26 +0100752 cairo_rectangle(ctx->cr, ctx->width/2+HALF_PAD-.5, ctx->height/2+HALF_PAD-.5, ctx->width/2-SIZE_PAD+1, ctx->height/2-SIZE_PAD+1);
Chris Wilsondb35f8c2013-08-21 13:36:29 +0100753 cairo_set_source_rgb(ctx->cr, .15, .15, .15);
754 cairo_set_line_width(ctx->cr, 1);
755 cairo_stroke(ctx->cr);
756
Chris Wilsone1ed5602013-08-18 18:17:05 +0100757 chart_add_sample(&go->gtt, go->gem_objects.total_gtt);
758 chart_add_sample(&go->aperture, go->gem_objects.total_aperture);
759
Chris Wilsone1ed5602013-08-18 18:17:05 +0100760 chart_draw(&go->gtt, ctx->cr);
761 chart_draw(&go->aperture, ctx->cr);
762
Chris Wilsone34fab52013-08-21 11:06:51 +0100763
Chris Wilson04a4fae2013-08-26 14:45:26 +0100764 y = ctx->height/2 + HALF_PAD + 12 - 2;
765 x = ctx->width/2 + HALF_PAD;
Chris Wilsone34fab52013-08-21 11:06:51 +0100766
767 y2 = y1 = y;
768 y2 += 14;
769 for (comm = go->gem_objects.comm; comm; comm = comm->next) {
770 if ((comm->bytes >> 20) == 0)
771 break;
Chris Wilson396fa1b2013-08-27 12:54:37 +0100772 y2 += 12;
Chris Wilsone34fab52013-08-21 11:06:51 +0100773 }
774 y1 += -12 - 2;
Chris Wilson396fa1b2013-08-27 12:54:37 +0100775 y2 += -12 + 4;
Chris Wilsone34fab52013-08-21 11:06:51 +0100776
Chris Wilson04a4fae2013-08-26 14:45:26 +0100777 cairo_rectangle(ctx->cr, x, y1, ctx->width/2-SIZE_PAD, y2-y1);
778 linear = cairo_pattern_create_linear(x, 0, x+ctx->width/2-SIZE_PAD, 0);
Chris Wilsone34fab52013-08-21 11:06:51 +0100779 cairo_pattern_add_color_stop_rgba(linear, 0, 0, 0, 0, .5);
780 cairo_pattern_add_color_stop_rgba(linear, 1, 0, 0, 0, .0);
781 cairo_set_source(ctx->cr, linear);
782 cairo_pattern_destroy(linear);
783 cairo_fill(ctx->cr);
784
Chris Wilsona932c732013-08-24 12:37:59 +0100785 sprintf(buf, "Total: %ldMB, %ld objects",
Chris Wilson3f512942013-08-18 18:24:43 +0100786 go->gem_objects.total_bytes >> 20, go->gem_objects.total_count);
Chris Wilsone1ed5602013-08-18 18:17:05 +0100787 cairo_set_source_rgba(ctx->cr, 1, 1, 1, 1);
Chris Wilson6a382002013-08-18 18:45:14 +0100788 cairo_move_to(ctx->cr, x, y);
Chris Wilsone1ed5602013-08-18 18:17:05 +0100789 cairo_show_text(ctx->cr, buf);
Chris Wilsonb1d2a782013-08-27 15:42:48 +0100790 y += 12;
Chris Wilsone1ed5602013-08-18 18:17:05 +0100791
Chris Wilson6ec1d2c2013-08-26 23:32:07 +0100792 cairo_set_source_rgba(ctx->cr, .8, .8, .8, 1);
Chris Wilsonb1d2a782013-08-27 15:42:48 +0100793 cairo_set_font_size(ctx->cr, 8);
Chris Wilsone1ed5602013-08-18 18:17:05 +0100794 for (comm = go->gem_objects.comm; comm; comm = comm->next) {
Chris Wilson3f512942013-08-18 18:24:43 +0100795 if ((comm->bytes >> 20) == 0)
796 break;
797
Chris Wilson6ec1d2c2013-08-26 23:32:07 +0100798 sprintf(buf, "%s %ldMB, %ld objects",
Chris Wilson3f512942013-08-18 18:24:43 +0100799 comm->name, comm->bytes >> 20, comm->count);
Chris Wilson6a382002013-08-18 18:45:14 +0100800 cairo_move_to(ctx->cr, x, y);
Chris Wilsone1ed5602013-08-18 18:17:05 +0100801 cairo_show_text(ctx->cr, buf);
Chris Wilson396fa1b2013-08-27 12:54:37 +0100802 y += 12;
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100803 }
804}
805
Chris Wilson5cb8c772013-08-20 19:24:33 +0100806static int take_snapshot;
807
808static void signal_snapshot(int sig)
809{
810 take_snapshot = sig;
811}
812
Chris Wilson68c63dd2013-08-24 10:00:36 +0100813static int get_sample_period(struct config *config)
814{
815 const char *value;
816
817 value = config_get_value(config, "sampling", "period");
818 if (value && atoi(value) > 0)
819 return atoi(value);
820
821 value = config_get_value(config, "sampling", "frequency");
822 if (value && atoi(value) > 0)
823 return 1000000 / atoi(value);
824
825 return 500000;
826}
827
Chris Wilson9bebbbc2013-08-28 12:37:14 +0100828static void overlay_snapshot(struct overlay_context *ctx)
829{
830 char buf[1024];
831 sprintf(buf, "/tmp/overlay-snapshot-%ld.png", (long)time(NULL));
832 cairo_surface_write_to_png(ctx->surface, buf);
833}
834
Chris Wilson4d3e10d2013-09-22 19:00:59 +0100835static void usage(const char *progname)
836{
837 printf("intel-gpu-overlay -- realtime display of GPU statistics\n");
838 printf("Usage: %s [options]\n", progname);
839 printf("\t--config|-c <string> | <filename>\t\t\tSpecify an ini-style configuration string or file\n");
840 printf("\t--geometry|-G <width>x<height>+<x-offset>+<y-offset>\tExact window placement and size\n");
841 printf("\t--position|-P (top|middle|bottom)-(left|centre|right)\tPlace the window in a particular corner\n");
842 printf("\t--size|-S <width>x<height> | <scale>%%\t\t\tWindow size\n");
843 printf("\t--help|-h\t\t\t\t\t\tThis help message\n");
844}
845
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100846int main(int argc, char **argv)
847{
Chris Wilson7c52a3c2013-08-22 15:07:48 +0100848 static struct option long_options[] = {
849 {"config", 1, 0, 'c'},
850 {"geometry", 1, 0, 'G'},
851 {"position", 1, 0, 'P'},
Chris Wilson1e65d5a2013-08-25 23:37:58 +0100852 {"size", 1, 0, 'S'},
Chris Wilson4d3e10d2013-09-22 19:00:59 +0100853 {"help", 0, 0, 'h'},
Chris Wilson7c52a3c2013-08-22 15:07:48 +0100854 {NULL, 0, 0, 0,}
855 };
Chris Wilson74032f42013-08-18 18:40:03 +0100856 struct overlay_context ctx;
Chris Wilson7c52a3c2013-08-22 15:07:48 +0100857 struct config config;
Chris Wilson68c63dd2013-08-24 10:00:36 +0100858 int index, sample_period;
Chris Wilson75ef3672013-08-28 12:40:20 +0100859 int daemonize = 1, renice = 0;
Chris Wilson7c52a3c2013-08-22 15:07:48 +0100860 int i;
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100861
Chris Wilson44d444a2015-06-24 17:01:21 +0100862 setlocale(LC_ALL, "");
Chris Wilson7c52a3c2013-08-22 15:07:48 +0100863 config_init(&config);
864
865 opterr = 0;
Chris Wilson2e127532016-07-22 14:27:08 +0100866 while ((i = getopt_long(argc, argv, "c:G:fhn?", long_options, &index)) != -1) {
Chris Wilson7c52a3c2013-08-22 15:07:48 +0100867 switch (i) {
868 case 'c':
869 config_parse_string(&config, optarg);
870 break;
871 case 'G':
872 config_set_value(&config, "window", "geometry", optarg);
873 break;
874 case 'P':
875 config_set_value(&config, "window", "position", optarg);
876 break;
Chris Wilson1e65d5a2013-08-25 23:37:58 +0100877 case 'S':
878 config_set_value(&config, "window", "size", optarg);
879 break;
Chris Wilson39f98122013-08-25 15:17:39 +0100880 case 'f':
881 daemonize = 0;
882 break;
Chris Wilson75ef3672013-08-28 12:40:20 +0100883 case 'n':
884 renice = -20;
885 if (optarg)
886 renice = atoi(optarg);
887 break;
Chris Wilson4d3e10d2013-09-22 19:00:59 +0100888 case 'h':
889 usage(argv[0]);
890 return 0;
Chris Wilson7c52a3c2013-08-22 15:07:48 +0100891 }
892 }
893
894 if (argc > optind) {
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100895 x11_overlay_stop();
896 return 0;
897 }
898
Chris Wilson74032f42013-08-18 18:40:03 +0100899 ctx.width = 640;
Chris Wilson6a382002013-08-18 18:45:14 +0100900 ctx.height = 236;
Chris Wilsond9291022013-08-25 13:15:55 +0100901 ctx.surface = NULL;
902 if (ctx.surface == NULL)
903 ctx.surface = x11_overlay_create(&config, &ctx.width, &ctx.height);
Chris Wilson74032f42013-08-18 18:40:03 +0100904 if (ctx.surface == NULL)
Chris Wilson7c52a3c2013-08-22 15:07:48 +0100905 ctx.surface = x11_window_create(&config, &ctx.width, &ctx.height);
Chris Wilson34e47802013-08-18 21:10:26 +0100906 if (ctx.surface == NULL)
Chris Wilsond9291022013-08-25 13:15:55 +0100907 ctx.surface = kms_overlay_create(&config, &ctx.width, &ctx.height);
908 if (ctx.surface == NULL)
Chris Wilson263da262015-04-26 10:16:39 +0100909 return ENXIO;
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100910
Chris Wilson39f98122013-08-25 15:17:39 +0100911 if (daemonize && daemon(0, 0))
912 return EINVAL;
913
Thomas Wood1dcace32015-09-07 11:32:05 +0100914 if (renice && (nice(renice) == -1))
915 fprintf(stderr, "Could not renice: %s\n", strerror(errno));
Chris Wilson75ef3672013-08-28 12:40:20 +0100916
Chris Wilson7c52a3c2013-08-22 15:07:48 +0100917 signal(SIGUSR1, signal_snapshot);
918
Chris Wilson55b8c332013-08-19 18:15:04 +0100919 debugfs_init();
920
Chris Wilson74032f42013-08-18 18:40:03 +0100921 init_gpu_top(&ctx, &ctx.gpu_top);
922 init_gpu_perf(&ctx, &ctx.gpu_perf);
923 init_gpu_freq(&ctx, &ctx.gpu_freq);
924 init_gem_objects(&ctx, &ctx.gem_objects);
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100925
Chris Wilson68c63dd2013-08-24 10:00:36 +0100926 sample_period = get_sample_period(&config);
927
Chris Wilson7c52a3c2013-08-22 15:07:48 +0100928 i = 0;
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100929 while (1) {
Chris Wilson474ce532013-08-29 12:01:38 +0100930 ctx.time = time(NULL);
931
Chris Wilson74032f42013-08-18 18:40:03 +0100932 ctx.cr = cairo_create(ctx.surface);
Chris Wilsoncbbd55a2013-08-17 20:04:11 +0100933 cairo_set_operator(ctx.cr, CAIRO_OPERATOR_CLEAR);
934 cairo_paint(ctx.cr);
935 cairo_set_operator(ctx.cr, CAIRO_OPERATOR_OVER);
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100936
Chris Wilson74032f42013-08-18 18:40:03 +0100937 show_gpu_top(&ctx, &ctx.gpu_top);
938 show_gpu_perf(&ctx, &ctx.gpu_perf);
939 show_gpu_freq(&ctx, &ctx.gpu_freq);
940 show_gem_objects(&ctx, &ctx.gem_objects);
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100941
Chris Wilsonea801962013-08-22 22:50:05 +0100942 {
943 char buf[80];
944 cairo_text_extents_t extents;
945 gethostname(buf, sizeof(buf));
946 cairo_set_source_rgb(ctx.cr, .5, .5, .5);
Chris Wilson04a4fae2013-08-26 14:45:26 +0100947 cairo_set_font_size(ctx.cr, PAD-2);
Chris Wilsonea801962013-08-22 22:50:05 +0100948 cairo_text_extents(ctx.cr, buf, &extents);
949 cairo_move_to(ctx.cr,
950 (ctx.width-extents.width)/2.,
951 1+extents.height);
952 cairo_show_text(ctx.cr, buf);
953 }
954
Chris Wilsoncbbd55a2013-08-17 20:04:11 +0100955 cairo_destroy(ctx.cr);
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100956
Chris Wilson74032f42013-08-18 18:40:03 +0100957 overlay_show(ctx.surface);
Chris Wilson5cb8c772013-08-20 19:24:33 +0100958
959 if (take_snapshot) {
Chris Wilson9bebbbc2013-08-28 12:37:14 +0100960 overlay_snapshot(&ctx);
Chris Wilson5cb8c772013-08-20 19:24:33 +0100961 take_snapshot = 0;
962 }
Chris Wilson68c63dd2013-08-24 10:00:36 +0100963
964 usleep(sample_period);
Chris Wilsonf9a50de2013-08-17 11:12:07 +0100965 }
966
967 return 0;
968}