The test-gfx helper simply renders a solid-color on all active pipelines. Useful to debug monitor-hotplugging and GPU selection. --- .gitignore | 1 + Makefile.am | 9 ++ src/libsystemd-gfx/test-gfx.c | 302 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 312 insertions(+) create mode 100644 src/libsystemd-gfx/test-gfx.c
diff --git a/.gitignore b/.gitignore index f4921f5..a61f68d 100644 --- a/.gitignore +++ b/.gitignore @@ -115,6 +115,7 @@ /test-env-replace /test-event /test-fileio +/test-gfx /test-hashmap /test-hostname /test-id128 diff --git a/Makefile.am b/Makefile.am index e8822b2..aa17876 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3878,6 +3878,14 @@ libsystemd_gfx_la_LIBADD = \ libudev-internal.la \ src/libsystemd-gfx/unifont.bin.lo +test_gfx_SOURCES = \ + src/libsystemd-gfx/test-gfx.c + +test_gfx_LDADD = \ + libsystemd-bus-internal.la \ + libsystemd-shared.la \ + libsystemd-gfx.la + test_kbd_SOURCES = \ src/libsystemd-gfx/test-kbd.c @@ -3892,6 +3900,7 @@ test_kbd_LDADD = \ libsystemd-gfx.la tests += \ + test-gfx \ test-kbd src/libsystemd-gfx/unifont.bin: make-unifont.py src/libsystemd-gfx/unifont.hex diff --git a/src/libsystemd-gfx/test-gfx.c b/src/libsystemd-gfx/test-gfx.c new file mode 100644 index 0000000..36157b6 --- /dev/null +++ b/src/libsystemd-gfx/test-gfx.c @@ -0,0 +1,302 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2013 David Herrmann <dh.herrm...@gmail.com> + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <errno.h> +#include <fcntl.h> +#include <getopt.h> +#include <inttypes.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <unistd.h> + +#include "build.h" +#include "def.h" +#include "log.h" +#include "macro.h" +#include "missing.h" +#include "sd-bus.h" +#include "sd-daemon.h" +#include "sd-event.h" +#include "sd-gfx.h" +#include "util.h" + +typedef struct Test Test; + +struct Test { + sd_event *event; + sd_event_source *sigs[_NSIG]; + sd_gfx_monitor *mon; +}; + +static bool arg_all; +static const char *arg_gpus; +static const char *arg_keymap; + +static void test_pipe_draw(sd_gfx_pipe *pipe) { + sd_gfx_plane *primary; + sd_gfx_fb *fb; + + primary = sd_gfx_pipe_get_primary_plane(pipe); + if (!primary) { + log_error("no primary plane on pipe"); + return; + } + + fb = sd_gfx_plane_get_front(primary); + if (!fb) { + log_error("no front-fb on primary plane"); + return; + } + + sd_gfx_fb_fill(fb, + 0xffaabb00, + 0, + 0, + sd_gfx_fb_get_width(fb), + sd_gfx_fb_get_height(fb)); +} + +static void test_card_fn(sd_gfx_card *card, void *fn_data, sd_gfx_card_event *ev) { + switch (ev->type) { + case SD_GFX_CARD_PIPE_WAKE_UP: + test_pipe_draw(ev->pipe); + break; + } +} + +static void test_add(Test *t, sd_gfx_card *card) { + sd_gfx_card_set_event_fn(card, test_card_fn); +} + +static void test_remove(Test *t, sd_gfx_card *card) { + sd_gfx_card_set_event_fn(card, NULL); +} + +static void test_event_fn(sd_gfx_monitor *mon, void *fn_data, sd_gfx_monitor_event *ev) { + struct Test *t = fn_data; + + switch (ev->type) { + case SD_GFX_MONITOR_CREATE: + if (ev->devtype == SD_GFX_DEV_CARD) + test_add(t, ev->card); + else + log_notice("unknown device of type %d", ev->devtype); + break; + case SD_GFX_MONITOR_DESTROY: + if (ev->devtype == SD_GFX_DEV_CARD) + test_remove(t, ev->card); + break; + default: + log_warning("unhandled monitor event: %d", ev->type); + break; + } +} + +static int test_signal_fn(sd_event_source *s, const struct signalfd_siginfo *ssi, void *data) { + Test *t = data; + + log_notice("catched signal %d, exiting..", (int)ssi->ssi_signo); + sd_event_request_quit(t->event); + + return 0; +} + +static int test_new(Test **out) { + static const int sigs[] = { + SIGINT, SIGTERM, SIGQUIT, SIGHUP, SIGPIPE, 0 + }; + unsigned int flags; + sigset_t mask; + Test *t; + int r, i; + + t = calloc(1, sizeof(*t)); + if (!t) + return log_oom(); + + r = sd_event_default(&t->event); + if (r < 0) { + log_error("cannot get default event-loop: %d", r); + goto err_t; + } + + sigemptyset(&mask); + for (i = 0; sigs[i]; ++i) { + sigaddset(&mask, sigs[i]); + r = sd_event_add_signal(t->event, + sigs[i], + test_signal_fn, + t, + &t->sigs[i]); + if (r < 0) { + log_error("cannot block signal %d: %d", + sigs[i], r); + goto err_sigs; + } + } + sigprocmask(SIG_BLOCK, &mask, NULL); + + flags = SD_GFX_MONITOR_DEFAULT; + if (arg_all) + flags |= SD_GFX_MONITOR_IGNORE_SEATS; + + r = sd_gfx_monitor_new(&t->mon, + SD_GFX_DEV_CARD, + flags, + t->event); + if (r < 0) + goto err_sigs; + + sd_gfx_monitor_set_fn_data(t->mon, t); + sd_gfx_monitor_set_event_fn(t->mon, test_event_fn); + sd_gfx_monitor_parse_cmdline(t->mon); + if (arg_gpus) + sd_gfx_monitor_set_gpus(t->mon, arg_gpus); + if (arg_keymap) + sd_gfx_monitor_set_keymap(t->mon, arg_keymap); + + *out = t; + return 0; + +err_sigs: + for (i = 0; t->sigs[i]; ++i) + sd_event_source_unref(t->sigs[i]); + sd_event_unref(t->event); +err_t: + free(t); + return r; +} + +static void test_free(Test *t) { + int i; + + if (!t) + return; + + sd_gfx_monitor_free(t->mon); + for (i = 0; t->sigs[i]; ++i) + sd_event_source_unref(t->sigs[i]); + sd_event_unref(t->event); + free(t); +} + +static int test_run(Test *t) { + return sd_event_loop(t->event); +} + +static int help(void) { + printf("%s [OPTIONS...] ...\n\n" + "sd-gfx graphics test.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --all Use all devices\n" + " --gpus=MATCH List of GPUs to use\n" + " --keymap=LMVO XKB keymap to use\n" + , program_invocation_short_name); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + enum { + ARG_VERSION = 0x100, + ARG_ALL, + ARG_GPUS, + ARG_KEYMAP, + }; + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "all", no_argument, NULL, ARG_ALL }, + { "gpus", required_argument, NULL, ARG_GPUS }, + { "keymap", required_argument, NULL, ARG_KEYMAP }, + {} + }; + int c; + + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) { + switch(c) { + case 'h': + return help(); + case ARG_VERSION: + puts(PACKAGE_STRING); + puts(SYSTEMD_FEATURES); + return 0; + case ARG_ALL: + arg_all = true; + break; + case ARG_GPUS: + arg_gpus = optarg; + break; + case ARG_KEYMAP: + arg_keymap = optarg; + break; + case '?': + return -EINVAL; + default: + assert_not_reached("Unhandled option"); + } + } + + if (optind < argc) { + log_error("This program does not take arguments."); + return -EINVAL; + } + + return 1; +} + +int main(int argc, char *argv[]) { + Test *t = NULL; + int r; + + log_set_target(LOG_TARGET_AUTO); + log_parse_environment(); + log_open(); + + umask(0022); + setlocale(LC_ALL, ""); + + r = parse_argv(argc, argv); + if (r < 0) + return EXIT_FAILURE; + if (r == 0) + return EXIT_SUCCESS; + + r = test_new(&t); + if (r < 0) + goto finish; + + r = test_run(t); + +finish: + if (t) + test_free(t); + + log_debug("exiting.."); + return abs(r); +} -- 1.8.4.2 _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel