2 * Copyright © 2013 Intel Corporation
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:
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
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
25 #include <sys/types.h>
43 #include "gem-interrupts.h"
44 #include "gem-objects.h"
51 #define is_power_of_two(x) (((x) & ((x)-1)) == 0)
55 #define SIZE_PAD (PAD + HALF_PAD)
57 const cairo_user_data_key_t overlay_key;
59 static void overlay_show(cairo_surface_t *surface)
61 struct overlay *overlay;
63 overlay = cairo_surface_get_user_data(surface, &overlay_key);
67 overlay->show(overlay);
71 static void overlay_position(cairo_surface_t *surface, enum position p)
73 struct overlay *overlay;
75 overlay = cairo_surface_get_user_data(surface, &overlay_key);
79 overlay->position(overlay, p);
82 static void overlay_hide(cairo_surface_t *surface)
84 struct overlay *overlay;
86 overlay = cairo_surface_get_user_data(surface, &overlay_key);
90 overlay->hide(overlay);
94 struct overlay_gpu_top {
95 struct gpu_top gpu_top;
96 struct cpu_top cpu_top;
97 struct chart busy[MAX_RINGS];
98 struct chart wait[MAX_RINGS];
102 struct overlay_gpu_perf {
103 struct gpu_perf gpu_perf;
106 struct overlay_gpu_freq {
107 struct gpu_freq gpu_freq;
109 struct gem_interrupts irqs;
111 struct chart current;
112 struct chart request;
113 struct chart power_chart;
117 struct overlay_gem_objects {
118 struct gem_objects gem_objects;
119 struct chart aperture;
124 struct overlay_context {
125 cairo_surface_t *surface;
129 struct overlay_gpu_top gpu_top;
130 struct overlay_gpu_perf gpu_perf;
131 struct overlay_gpu_freq gpu_freq;
132 struct overlay_gem_objects gem_objects;
135 static void init_gpu_top(struct overlay_context *ctx,
136 struct overlay_gpu_top *gt)
138 const double rgba[][4] = {
139 { 1, 0.25, 0.25, 1 },
140 { 0.25, 1, 0.25, 1 },
141 { 0.25, 0.25, 1, 1 },
146 gpu_top_init(>->gpu_top);
147 memset(>->cpu, 0, sizeof(gt->cpu));
149 chart_init(>->cpu, "CPU", 120);
150 chart_set_position(>->cpu, PAD, PAD);
151 chart_set_size(>->cpu, ctx->width/2 - SIZE_PAD, ctx->height/2 - SIZE_PAD);
152 chart_set_stroke_rgba(>->cpu, 0.75, 0.25, 0.75, 1.);
153 chart_set_mode(>->cpu, CHART_STROKE);
154 chart_set_range(>->cpu, 0, 100);
156 for (n = 0; n < gt->gpu_top.num_rings; n++) {
157 chart_init(>->busy[n],
158 gt->gpu_top.ring[n].name,
160 chart_set_position(>->busy[n], PAD, PAD);
161 chart_set_size(>->busy[n], ctx->width/2 - SIZE_PAD, ctx->height/2 - SIZE_PAD);
162 chart_set_stroke_rgba(>->busy[n],
163 rgba[n][0], rgba[n][1], rgba[n][2], rgba[n][3]);
164 chart_set_mode(>->busy[n], CHART_STROKE);
165 chart_set_range(>->busy[n], 0, 100);
168 for (n = 0; n < gt->gpu_top.num_rings; n++) {
169 chart_init(>->wait[n],
170 gt->gpu_top.ring[n].name,
172 chart_set_position(>->wait[n], PAD, PAD);
173 chart_set_size(>->wait[n], ctx->width/2 - SIZE_PAD, ctx->height/2 - SIZE_PAD);
174 chart_set_fill_rgba(>->wait[n],
175 rgba[n][0], rgba[n][1], rgba[n][2], rgba[n][3] * 0.70);
176 chart_set_mode(>->wait[n], CHART_FILL);
177 chart_set_range(>->wait[n], 0, 100);
181 static void show_gpu_top(struct overlay_context *ctx, struct overlay_gpu_top *gt)
183 int y, y1, y2, n, update, len;
184 cairo_pattern_t *linear;
187 update = gpu_top_update(>->gpu_top);
189 cairo_rectangle(ctx->cr, PAD-.5, PAD-.5, ctx->width/2-SIZE_PAD+1, ctx->height/2-SIZE_PAD+1);
190 cairo_set_source_rgb(ctx->cr, .15, .15, .15);
191 cairo_set_line_width(ctx->cr, 1);
192 cairo_stroke(ctx->cr);
194 if (update && cpu_top_update(>->cpu_top) == 0)
195 chart_add_sample(>->cpu, gt->cpu_top.busy);
197 for (n = 0; n < gt->gpu_top.num_rings; n++) {
199 chart_add_sample(>->wait[n],
200 gt->gpu_top.ring[n].u.u.wait + gt->gpu_top.ring[n].u.u.sema);
201 chart_draw(>->wait[n], ctx->cr);
203 for (n = 0; n < gt->gpu_top.num_rings; n++) {
205 chart_add_sample(>->busy[n],
206 gt->gpu_top.ring[n].u.u.busy);
207 chart_draw(>->busy[n], ctx->cr);
209 chart_draw(>->cpu, ctx->cr);
212 y2 = y1 + (gt->gpu_top.num_rings+1) * 14 + 4;
214 cairo_rectangle(ctx->cr, PAD, y1, ctx->width/2-SIZE_PAD, y2-y1);
215 linear = cairo_pattern_create_linear(PAD, 0, PAD+ctx->width/2-SIZE_PAD, 0);
216 cairo_pattern_add_color_stop_rgba(linear, 0, 0, 0, 0, .5);
217 cairo_pattern_add_color_stop_rgba(linear, 1, 0, 0, 0, .0);
218 cairo_set_source(ctx->cr, linear);
219 cairo_pattern_destroy(linear);
223 cairo_set_source_rgba(ctx->cr, 0.75, 0.25, 0.75, 1.);
224 cairo_move_to(ctx->cr, PAD, y);
225 sprintf(txt, "CPU: %d%% busy", gt->cpu_top.busy);
226 cairo_show_text(ctx->cr, txt);
229 for (n = 0; n < gt->gpu_top.num_rings; n++) {
230 struct chart *c =>->busy[n];
232 len = sprintf(txt, "%s: %d%% busy",
233 gt->gpu_top.ring[n].name,
234 gt->gpu_top.ring[n].u.u.busy);
235 if (gt->gpu_top.ring[n].u.u.wait)
236 len += sprintf(txt + len, ", %d%% wait",
237 gt->gpu_top.ring[n].u.u.wait);
238 if (gt->gpu_top.ring[n].u.u.sema)
239 len += sprintf(txt + len, ", %d%% sema",
240 gt->gpu_top.ring[n].u.u.sema);
242 cairo_set_source_rgba(ctx->cr,
247 cairo_move_to(ctx->cr, PAD, y);
248 cairo_show_text(ctx->cr, txt);
253 static void init_gpu_perf(struct overlay_context *ctx,
254 struct overlay_gpu_perf *gp)
256 gpu_perf_init(&gp->gpu_perf, 0);
259 static char *get_comm(pid_t pid, char *comm, int len)
265 snprintf(filename, sizeof(filename), "/proc/%d/comm", pid);
267 fd = open(filename, 0);
269 len = read(fd, comm, len);
278 static void show_gpu_perf(struct overlay_context *ctx, struct overlay_gpu_perf *gp)
280 static int last_color;
281 const double rgba[][4] = {
282 { 1, 0.25, 0.25, 1 },
283 { 0.25, 1, 0.25, 1 },
284 { 0.25, 0.25, 1, 1 },
287 struct gpu_perf_comm *comm, **prev;
288 const char *ring_name[] = {
295 cairo_pattern_t *linear;
298 cairo_rectangle(ctx->cr, ctx->width/2+HALF_PAD-.5, PAD-.5, ctx->width/2-SIZE_PAD+1, ctx->height/2-SIZE_PAD+1);
299 cairo_set_source_rgb(ctx->cr, .15, .15, .15);
300 cairo_set_line_width(ctx->cr, 1);
301 cairo_stroke(ctx->cr);
303 if (gp->gpu_perf.error) {
304 cairo_text_extents_t extents;
305 cairo_text_extents(ctx->cr, gp->gpu_perf.error, &extents);
306 cairo_move_to(ctx->cr,
307 ctx->width/2+HALF_PAD + (ctx->width/2-SIZE_PAD - extents.width)/2.,
308 PAD + (ctx->height/2-SIZE_PAD + extents.height)/2.);
309 cairo_show_text(ctx->cr, gp->gpu_perf.error);
313 gpu_perf_update(&gp->gpu_perf);
316 x = ctx->width/2 + HALF_PAD;
319 for (comm = gp->gpu_perf.comm; comm; comm = comm->next) {
322 if (comm->user_data == NULL) {
323 comm->user_data = malloc(sizeof(struct chart));
324 if (comm->user_data == NULL)
327 chart_init(comm->user_data, comm->name, 120);
328 chart_set_position(comm->user_data, ctx->width/2+HALF_PAD, PAD);
329 chart_set_size(comm->user_data, ctx->width/2-SIZE_PAD, ctx->height/2 - SIZE_PAD);
330 chart_set_mode(comm->user_data, CHART_STROKE);
331 chart_set_stroke_rgba(comm->user_data,
335 rgba[last_color][3]);
336 last_color = (last_color + 1) % 4;
337 chart_set_stroke_width(comm->user_data, 1);
341 for (n = 0; n < 3; n++)
342 total += comm->nr_requests[n];
343 chart_add_sample(comm->user_data, total);
346 range[0] = range[1] = 0;
347 for (comm = gp->gpu_perf.comm; comm; comm = comm->next)
348 chart_get_range(comm->user_data, range);
351 for (comm = gp->gpu_perf.comm; comm; comm = comm->next) {
352 chart_set_range(comm->user_data, range[0], range[1]);
353 chart_draw(comm->user_data, ctx->cr);
359 cairo_rectangle(ctx->cr, x, y1, ctx->width/2-SIZE_PAD, y2-y1);
360 linear = cairo_pattern_create_linear(x, 0, x + ctx->width/2-SIZE_PAD, 0);
361 cairo_pattern_add_color_stop_rgba(linear, 0, 0, 0, 0, .5);
362 cairo_pattern_add_color_stop_rgba(linear, 1, 0, 0, 0, .0);
363 cairo_set_source(ctx->cr, linear);
364 cairo_pattern_destroy(linear);
367 for (prev = &gp->gpu_perf.comm; (comm = *prev) != NULL; ) {
368 int need_comma = 0, len;
370 if (comm->name[0] == '\0')
373 len = sprintf(buf, "%s:", comm->name);
374 for (n = 0; n < 3; n++) {
375 if (comm->nr_requests[n] == 0)
377 len += sprintf(buf + len, "%s %d%s", need_comma ? "," : "", comm->nr_requests[n], ring_name[n]);
380 if (comm->wait_time) {
381 if (comm->wait_time > 1000*1000) {
382 len += sprintf(buf + len, "%s %.1fms waits",
383 need_comma ? "," : "",
384 comm->wait_time / (1000*1000.));
385 } else if (comm->wait_time > 100) {
386 len += sprintf(buf + len, "%s %.1fus waits",
387 need_comma ? "," : "",
388 comm->wait_time / 1000.);
390 len += sprintf(buf, "%s %.0fns waits",
391 need_comma ? "," : "",
392 (double)comm->wait_time);
398 len += sprintf(buf + len, "%s %d syncs",
399 need_comma ? "," : "",
405 if (comm->user_data) {
406 struct chart *c = comm->user_data;
407 cairo_set_source_rgba(ctx->cr,
413 cairo_set_source_rgba(ctx->cr, 1, 1, 1, 1);
414 cairo_move_to(ctx->cr, x, y);
415 cairo_show_text(ctx->cr, buf);
419 memset(comm->nr_requests, 0, sizeof(comm->nr_requests));
420 if (strcmp(comm->name, get_comm(comm->pid, buf, sizeof(buf)))) {
422 if (comm->user_data) {
423 chart_fini(comm->user_data);
424 free(comm->user_data);
432 int has_flips = 0, len;
433 for (n = 0; n < 4; n++) {
434 if (gp->gpu_perf.flip_complete[n])
438 len = sprintf(buf, "Flips:");
439 for (n = 0; n < has_flips; n++)
440 len += sprintf(buf + len, "%s %d",
442 gp->gpu_perf.flip_complete[n]);
444 sprintf(buf, "Flips: 0");
446 memset(gp->gpu_perf.flip_complete, 0, sizeof(gp->gpu_perf.flip_complete));
448 cairo_set_source_rgba(ctx->cr, 1, 1, 1, 1);
449 cairo_move_to(ctx->cr, x, y);
450 cairo_show_text(ctx->cr, buf);
454 static void init_gpu_freq(struct overlay_context *ctx,
455 struct overlay_gpu_freq *gf)
457 if (gpu_freq_init(&gf->gpu_freq) == 0) {
458 chart_init(&gf->current, "current", 120);
459 chart_set_position(&gf->current, PAD, ctx->height/2 + HALF_PAD);
460 chart_set_size(&gf->current, ctx->width/2 - SIZE_PAD, ctx->height/2 - SIZE_PAD);
461 chart_set_stroke_rgba(&gf->current, 0.75, 0.25, 0.50, 1.);
462 chart_set_mode(&gf->current, CHART_STROKE);
463 chart_set_smooth(&gf->current, CHART_LINE);
464 chart_set_range(&gf->current, 0, gf->gpu_freq.max);
466 chart_init(&gf->request, "request", 120);
467 chart_set_position(&gf->request, PAD, ctx->height/2 + HALF_PAD);
468 chart_set_size(&gf->request, ctx->width/2 - SIZE_PAD, ctx->height/2 - SIZE_PAD);
469 chart_set_fill_rgba(&gf->request, 0.25, 0.25, 0.50, 1.);
470 chart_set_mode(&gf->request, CHART_FILL);
471 chart_set_smooth(&gf->request, CHART_LINE);
472 chart_set_range(&gf->request, 0, gf->gpu_freq.max);
475 if (power_init(&gf->power) == 0) {
476 chart_init(&gf->power_chart, "power", 120);
477 chart_set_position(&gf->power_chart, PAD, ctx->height/2 + HALF_PAD);
478 chart_set_size(&gf->power_chart, ctx->width/2 - SIZE_PAD, ctx->height/2 - SIZE_PAD);
479 chart_set_stroke_rgba(&gf->power_chart, 0.45, 0.55, 0.45, 1.);
484 gem_interrupts_init(&gf->irqs);
487 static void show_gpu_freq(struct overlay_context *ctx, struct overlay_gpu_freq *gf)
492 int has_freq = gpu_freq_update(&gf->gpu_freq) == 0;
493 int has_rc6 = rc6_update(&gf->rc6) == 0;
494 int has_power = power_update(&gf->power) == 0;
495 int has_irqs = gem_interrupts_update(&gf->irqs) == 0;
496 cairo_pattern_t *linear;
498 cairo_rectangle(ctx->cr, PAD-.5, ctx->height/2+HALF_PAD-.5, ctx->width/2-SIZE_PAD+1, ctx->height/2-SIZE_PAD+1);
499 cairo_set_source_rgb(ctx->cr, .15, .15, .15);
500 cairo_set_line_width(ctx->cr, 1);
501 cairo_stroke(ctx->cr);
503 if (gf->gpu_freq.error) {
504 const char *txt = "GPU frequency not found in debugfs";
505 cairo_text_extents_t extents;
506 cairo_text_extents(ctx->cr, txt, &extents);
507 cairo_move_to(ctx->cr,
508 PAD + (ctx->width/2-SIZE_PAD - extents.width)/2.,
509 ctx->height/2+HALF_PAD + (ctx->height/2-SIZE_PAD + extents.height)/2.);
510 cairo_show_text(ctx->cr, txt);
515 if (gf->gpu_freq.current)
516 chart_add_sample(&gf->current, gf->gpu_freq.current);
517 if (gf->gpu_freq.request)
518 chart_add_sample(&gf->request, gf->gpu_freq.request);
520 chart_draw(&gf->request, ctx->cr);
521 chart_draw(&gf->current, ctx->cr);
525 chart_add_sample(&gf->power_chart, gf->power.power_mW);
526 if (gf->power.new_sample) {
527 if (gf->power.power_mW > gf->power_max)
528 gf->power_max = gf->power.power_mW;
529 chart_set_range(&gf->power_chart, 0, gf->power_max);
530 gf->power.new_sample = 0;
532 chart_draw(&gf->power_chart, ctx->cr);
535 y = ctx->height/2 + HALF_PAD + 12 - 2;
551 cairo_rectangle(ctx->cr, PAD, y1, ctx->width/2-SIZE_PAD, y2-y1);
552 linear = cairo_pattern_create_linear(PAD, 0, PAD+ctx->width/2-SIZE_PAD, 0);
553 cairo_pattern_add_color_stop_rgba(linear, 0, 0, 0, 0, .5);
554 cairo_pattern_add_color_stop_rgba(linear, 1, 0, 0, 0, .0);
555 cairo_set_source(ctx->cr, linear);
556 cairo_pattern_destroy(linear);
560 len = sprintf(buf, "Frequency: %dMHz", gf->gpu_freq.current);
561 if (gf->gpu_freq.request)
562 sprintf(buf + len, " (requested %dMHz)", gf->gpu_freq.request);
563 cairo_set_source_rgba(ctx->cr, 1, 1, 1, 1);
564 cairo_move_to(ctx->cr, PAD, y);
565 cairo_show_text(ctx->cr, buf);
568 sprintf(buf, "min: %dMHz, max: %dMHz", gf->gpu_freq.min, gf->gpu_freq.max);
569 cairo_move_to(ctx->cr, PAD, y);
570 cairo_show_text(ctx->cr, buf);
575 sprintf(buf, "RC6: %d%%", gf->rc6.rc6_combined);
576 cairo_move_to(ctx->cr, PAD, y);
577 cairo_show_text(ctx->cr, buf);
578 if (gf->rc6.rc6_combined && !is_power_of_two(gf->rc6.enabled)) {
581 txt = buf + sprintf(buf, " (");
582 if (gf->rc6.enabled & 1) {
584 len += sprintf(txt + len, ", ");
585 len += sprintf(txt + len, "rc6=%d%%", gf->rc6.rc6);
587 if (gf->rc6.enabled & 2) {
589 len += sprintf(txt + len, ", ");
590 len += sprintf(txt + len, "rc6p=%d%%", gf->rc6.rc6p);
592 if (gf->rc6.enabled & 4) {
594 len += sprintf(txt + len, ", ");
595 len += sprintf(txt + len, "rc6pp=%d%%", gf->rc6.rc6pp);
597 sprintf(txt + len, ")");
598 cairo_show_text(ctx->cr, buf);
604 sprintf(buf, "Power: %llumW", (long long unsigned)gf->power.power_mW);
605 cairo_move_to(ctx->cr, PAD, y);
606 cairo_show_text(ctx->cr, buf);
611 sprintf(buf, "Interrupts: %llu", (long long unsigned)gf->irqs.delta);
612 cairo_move_to(ctx->cr, PAD, y);
613 cairo_show_text(ctx->cr, buf);
618 static void init_gem_objects(struct overlay_context *ctx,
619 struct overlay_gem_objects *go)
621 go->error = gem_objects_init(&go->gem_objects);
625 chart_init(&go->aperture, "aperture", 120);
626 chart_set_position(&go->aperture, ctx->width/2+HALF_PAD, ctx->height/2 + HALF_PAD);
627 chart_set_size(&go->aperture, ctx->width/2 - SIZE_PAD, ctx->height/2 - SIZE_PAD);
628 chart_set_stroke_rgba(&go->aperture, 0.75, 0.25, 0.50, 1.);
629 chart_set_mode(&go->aperture, CHART_STROKE);
630 chart_set_range(&go->aperture, 0, go->gem_objects.max_gtt);
632 chart_init(&go->gtt, "gtt", 120);
633 chart_set_position(&go->gtt, ctx->width/2+HALF_PAD, ctx->height/2 + HALF_PAD);
634 chart_set_size(&go->gtt, ctx->width/2 - SIZE_PAD, ctx->height/2 - SIZE_PAD);
635 chart_set_fill_rgba(&go->gtt, 0.25, 0.5, 0.5, 1.);
636 chart_set_mode(&go->gtt, CHART_FILL);
637 chart_set_range(&go->gtt, 0, go->gem_objects.max_gtt);
640 static void show_gem_objects(struct overlay_context *ctx, struct overlay_gem_objects *go)
642 struct gem_objects_comm *comm;
644 cairo_pattern_t *linear;
648 go->error = gem_objects_update(&go->gem_objects);
652 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);
653 cairo_set_source_rgb(ctx->cr, .15, .15, .15);
654 cairo_set_line_width(ctx->cr, 1);
655 cairo_stroke(ctx->cr);
657 chart_add_sample(&go->gtt, go->gem_objects.total_gtt);
658 chart_add_sample(&go->aperture, go->gem_objects.total_aperture);
660 chart_draw(&go->gtt, ctx->cr);
661 chart_draw(&go->aperture, ctx->cr);
664 y = ctx->height/2 + HALF_PAD + 12 - 2;
665 x = ctx->width/2 + HALF_PAD;
669 for (comm = go->gem_objects.comm; comm; comm = comm->next) {
670 if ((comm->bytes >> 20) == 0)
677 cairo_rectangle(ctx->cr, x, y1, ctx->width/2-SIZE_PAD, y2-y1);
678 linear = cairo_pattern_create_linear(x, 0, x+ctx->width/2-SIZE_PAD, 0);
679 cairo_pattern_add_color_stop_rgba(linear, 0, 0, 0, 0, .5);
680 cairo_pattern_add_color_stop_rgba(linear, 1, 0, 0, 0, .0);
681 cairo_set_source(ctx->cr, linear);
682 cairo_pattern_destroy(linear);
685 sprintf(buf, "Total: %ldMB, %ld objects",
686 go->gem_objects.total_bytes >> 20, go->gem_objects.total_count);
687 cairo_set_source_rgba(ctx->cr, 1, 1, 1, 1);
688 cairo_move_to(ctx->cr, x, y);
689 cairo_show_text(ctx->cr, buf);
692 cairo_set_source_rgba(ctx->cr, .8, .8, .8, 1);
693 for (comm = go->gem_objects.comm; comm; comm = comm->next) {
694 if ((comm->bytes >> 20) == 0)
697 sprintf(buf, "%s %ldMB, %ld objects",
698 comm->name, comm->bytes >> 20, comm->count);
699 cairo_move_to(ctx->cr, x, y);
700 cairo_show_text(ctx->cr, buf);
705 static int take_snapshot;
707 static void signal_snapshot(int sig)
712 static int get_sample_period(struct config *config)
716 value = config_get_value(config, "sampling", "period");
717 if (value && atoi(value) > 0)
720 value = config_get_value(config, "sampling", "frequency");
721 if (value && atoi(value) > 0)
722 return 1000000 / atoi(value);
727 int main(int argc, char **argv)
729 static struct option long_options[] = {
730 {"config", 1, 0, 'c'},
731 {"geometry", 1, 0, 'G'},
732 {"position", 1, 0, 'P'},
736 struct overlay_context ctx;
737 struct config config;
738 int index, sample_period;
742 config_init(&config);
745 while ((i = getopt_long(argc, argv, "c:f", long_options, &index)) != -1) {
748 config_parse_string(&config, optarg);
751 config_set_value(&config, "window", "geometry", optarg);
754 config_set_value(&config, "window", "position", optarg);
757 config_set_value(&config, "window", "size", optarg);
773 if (ctx.surface == NULL)
774 ctx.surface = x11_overlay_create(&config, &ctx.width, &ctx.height);
775 if (ctx.surface == NULL)
776 ctx.surface = x11_window_create(&config, &ctx.width, &ctx.height);
777 if (ctx.surface == NULL)
778 ctx.surface = kms_overlay_create(&config, &ctx.width, &ctx.height);
779 if (ctx.surface == NULL)
782 if (daemonize && daemon(0, 0))
785 signal(SIGUSR1, signal_snapshot);
789 init_gpu_top(&ctx, &ctx.gpu_top);
790 init_gpu_perf(&ctx, &ctx.gpu_perf);
791 init_gpu_freq(&ctx, &ctx.gpu_freq);
792 init_gem_objects(&ctx, &ctx.gem_objects);
794 sample_period = get_sample_period(&config);
798 ctx.cr = cairo_create(ctx.surface);
799 cairo_set_operator(ctx.cr, CAIRO_OPERATOR_CLEAR);
801 cairo_set_operator(ctx.cr, CAIRO_OPERATOR_OVER);
803 show_gpu_top(&ctx, &ctx.gpu_top);
804 show_gpu_perf(&ctx, &ctx.gpu_perf);
805 show_gpu_freq(&ctx, &ctx.gpu_freq);
806 show_gem_objects(&ctx, &ctx.gem_objects);
810 cairo_text_extents_t extents;
811 gethostname(buf, sizeof(buf));
812 cairo_set_source_rgb(ctx.cr, .5, .5, .5);
813 cairo_set_font_size(ctx.cr, PAD-2);
814 cairo_text_extents(ctx.cr, buf, &extents);
815 cairo_move_to(ctx.cr,
816 (ctx.width-extents.width)/2.,
818 cairo_show_text(ctx.cr, buf);
821 cairo_destroy(ctx.cr);
823 overlay_show(ctx.surface);
827 sprintf(buf, "overlay-snapshot-%d.png", i-1);
828 cairo_surface_write_to_png(ctx.surface, buf);
832 usleep(sample_period);