From 7c52a3cf5243b42b632fd73789d1b484e81b9b0c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 22 Aug 2013 15:07:48 +0100 Subject: overlay: Rudiments of config files and option parsing Signed-off-by: Chris Wilson --- overlay/Makefile.am | 9 +- overlay/config.c | 282 ++++++++++++++++++++++++++++++++++++++++++++++ overlay/overlay.c | 40 ++++++- overlay/overlay.h | 30 ++++- overlay/x11/position.c | 131 +++++++++++++++++++++ overlay/x11/position.h | 38 +++++++ overlay/x11/x11-overlay.c | 56 ++++----- overlay/x11/x11-window.c | 41 +------ 8 files changed, 541 insertions(+), 86 deletions(-) create mode 100644 overlay/config.c create mode 100644 overlay/x11/position.c create mode 100644 overlay/x11/position.h (limited to 'overlay') diff --git a/overlay/Makefile.am b/overlay/Makefile.am index 75a3338a..52a61270 100644 --- a/overlay/Makefile.am +++ b/overlay/Makefile.am @@ -8,10 +8,9 @@ LDADD = $(DRM_LIBS) $(PCIACCESS_LIBS) $(CAIRO_LIBS) $(OVERLAY_LIBS) intel_gpu_overlay_SOURCES = \ i915_pciids.h \ - overlay.h \ - overlay.c \ chart.h \ chart.c \ + config.c \ cpu-top.h \ cpu-top.c \ debugfs.h \ @@ -26,6 +25,8 @@ intel_gpu_overlay_SOURCES = \ gpu-freq.c \ igfx.h \ igfx.c \ + overlay.h \ + overlay.c \ power.h \ power.c \ rc6.h \ @@ -33,6 +34,7 @@ intel_gpu_overlay_SOURCES = \ $(NULL) if BUILD_OVERLAY_XLIB +both_x11_sources = x11/position.c x11/position.h AM_CFLAGS += $(OVERLAY_XLIB_CFLAGS) LDADD += $(OVERLAY_XLIB_LIBS) intel_gpu_overlay_SOURCES += \ @@ -41,6 +43,7 @@ intel_gpu_overlay_SOURCES += \ endif if BUILD_OVERLAY_XVLIB +both_x11_sources = x11/x11-position.c AM_CFLAGS += $(OVERLAY_XVLIB_CFLAGS) LDADD += $(OVERLAY_XVLIB_LIBS) intel_gpu_overlay_SOURCES += \ @@ -52,4 +55,6 @@ intel_gpu_overlay_SOURCES += \ $(NULL) endif +intel_gpu_overlay_SOURCES += $(both_x11_sources) + EXTRA_DIST=README diff --git a/overlay/config.c b/overlay/config.c new file mode 100644 index 00000000..f0f7ce8b --- /dev/null +++ b/overlay/config.c @@ -0,0 +1,282 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "overlay.h" + +#define DEFAULT_SECTION "window" + +static const char *skip_whitespace(const char *s, const char *end) +{ + while (s < end && isspace(*s)) + s++; + return s; +} + +static const char *trim_whitespace(const char *s, const char *end) +{ + if (end == NULL) + return end; + + while (end > s && isspace(*--end)) + ; + + return end + 1; +} + +static const char *skip_past_newline(const char *s, const char *end) +{ + while (s < end && *s++ != '\n') + ; + + return s; +} + +static const char *find(const char *s, const char *end, int c) +{ + while (s < end && *s != c) { + if (*s == '#') + break; + + if (*s == '\n') + return NULL; + s++; + } + + return s; +} + +static int parse(const char *buf, int len, + int (*func)(const char *section, + const char *name, + const char *value, + void *data), + void *data) +{ + char section[128] = DEFAULT_SECTION, name[128], value[128]; + const char *buf_end = buf + len; + const char *end; + int line = 0; + + for (line = 0 ; ++line; buf = skip_past_newline(buf, buf_end)) { + ++line; + buf = skip_whitespace(buf, buf_end); + if (buf >= buf_end) + break; + + if (*buf == ';' || *buf == '#') { + /* comment */ + } else if (*buf == '[') { /* new section */ + end = find(++buf, buf_end, ']'); + end = trim_whitespace(buf, end); + if (end <= buf) + continue; + + len = end - buf; + if (len == 0 || len >= sizeof(section)) + return line; + + memcpy(section, buf, len); + section[len] = '\0'; + } else { /* name = value */ + const char *sep; + int has_value = 1; + + sep = find(buf, buf_end, '='); + if (sep == NULL) + sep = find(buf, buf_end, ':'); + if (sep == NULL) { + sep = find(buf, buf_end, '\n'); + has_value = 0; + } + end = trim_whitespace(buf, sep); + if (end <= buf) + continue; + + len = end - buf; + if (len == 0 || len >= sizeof(name)) + return line; + + memcpy(name, buf, len); + name[len] = '\0'; + + if (has_value) { + buf = skip_whitespace(sep + 1, buf_end); + end = find(buf, buf_end, '\n'); + end = trim_whitespace(buf, end); + + len = end - buf; + if (len >= sizeof(name)) + return line; + + memcpy(value, buf, len); + value[len] = '\0'; + } else + value[0] = '\0'; + + if (!func(section, name, value, data)) + return line; + } + } + + return 0; +} + +static int add_value(const char *section, + const char *name, + const char *value, + void *data) +{ + struct config *c = data; + struct config_section *s; + struct config_value *v, **prev; + + for (s = c->sections; s != NULL; s = s->next) + if (strcmp(s->name, section) == 0) + break; + if (s == NULL) { + int len = strlen(section) + 1; + + s = malloc(sizeof(*s)+len); + if (s == NULL) + return 0; + + memcpy(s->name, section, len); + s->next = c->sections; + c->sections = s; + } + + for (prev = &s->values; (v = *prev) != NULL; prev = &v->next) { + if (strcmp(v->name, name) == 0) { + *prev = v->next; + free(v); + break; + } + } + { + int name_len = strlen(name) + 1; + int value_len = *value ? strlen(value) + 1 : 0; + + v = malloc(sizeof(*v) + name_len + value_len); + if (v == NULL) + return 0; + + v->name = memcpy(v+1, name, name_len); + + if (*value) + v->value = memcpy(v->name + name_len, value, value_len); + else + v->value = NULL; + + v->next = s->values; + s->values = v; + } + + return 1; +} + +static int config_init_from_file(struct config *config, const char *filename) +{ + struct stat st; + int fd, err = -1; + char *str; + + fd = open(filename, 0); + if (fd < 0) + return -1; + + if (fstat(fd, &st) < 0) + goto err_fd; + + if ((str = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == (void *)-1) + goto err_fd; + + err = parse(str, st.st_size, add_value, config); + munmap(str, st.st_size); + +err_fd: + close(fd); + return err; +} + +void config_init(struct config *config) +{ + memset(config, 0, sizeof(*config)); +} + +void config_parse_string(struct config *config, const char *str) +{ + int err; + + if (str == NULL) + return; + + err = config_init_from_file(config, str); + if (err == -1) + err = parse(str, strlen(str), add_value, config); + if (err) { + fprintf(stderr, "Failed to parse config string at line %d\n", err); + exit(1); + } +} + +void config_set_value(struct config *c, + const char *section, + const char *name, + const char *value) +{ + add_value(section, name, value, c); +} + +const char *config_get_value(struct config *c, + const char *section, + const char *name) +{ + struct config_section *s; + struct config_value *v; + + for (s = c->sections; s != NULL; s = s->next) { + if (strcmp(s->name, section)) + continue; + + for (v = s->values; v != NULL; v = v->next) { + if (strcmp(v->name, name)) + continue; + + return v->value; + } + } + + return NULL; +} diff --git a/overlay/overlay.c b/overlay/overlay.c index e783a6f4..ce3b6453 100644 --- a/overlay/overlay.c +++ b/overlay/overlay.c @@ -33,9 +33,11 @@ #include #include #include +#include #include "overlay.h" #include "chart.h" +#include "config.h" #include "cpu-top.h" #include "debugfs.h" #include "gem-objects.h" @@ -710,24 +712,49 @@ static void signal_snapshot(int sig) int main(int argc, char **argv) { + static struct option long_options[] = { + {"config", 1, 0, 'c'}, + {"geometry", 1, 0, 'G'}, + {"position", 1, 0, 'P'}, + {NULL, 0, 0, 0,} + }; struct overlay_context ctx; - int i = 0; + struct config config; + int index; + int i; + + config_init(&config); + + opterr = 0; + while ((i = getopt_long(argc, argv, "c:", long_options, &index)) != -1) { + switch (i) { + case 'c': + config_parse_string(&config, optarg); + break; + case 'G': + config_set_value(&config, "window", "geometry", optarg); + break; + case 'P': + config_set_value(&config, "window", "position", optarg); + break; + } + } - if (argc > 1) { + if (argc > optind) { x11_overlay_stop(); return 0; } - signal(SIGUSR1, signal_snapshot); - ctx.width = 640; ctx.height = 236; - ctx.surface = x11_overlay_create(POS_TOP_RIGHT, &ctx.width, &ctx.height); + ctx.surface = x11_overlay_create(&config, &ctx.width, &ctx.height); if (ctx.surface == NULL) - ctx.surface = x11_window_create(POS_TOP_RIGHT, &ctx.width, &ctx.height); + ctx.surface = x11_window_create(&config, &ctx.width, &ctx.height); if (ctx.surface == NULL) return ENOMEM; + signal(SIGUSR1, signal_snapshot); + debugfs_init(); init_gpu_top(&ctx, &ctx.gpu_top); @@ -735,6 +762,7 @@ int main(int argc, char **argv) init_gpu_freq(&ctx, &ctx.gpu_freq); init_gem_objects(&ctx, &ctx.gem_objects); + i = 0; while (1) { usleep(500*1000); diff --git a/overlay/overlay.h b/overlay/overlay.h index 7794b577..f7b94d16 100644 --- a/overlay/overlay.h +++ b/overlay/overlay.h @@ -64,18 +64,40 @@ struct overlay { extern const cairo_user_data_key_t overlay_key; +struct config { + struct config_section { + struct config_section *next; + struct config_value { + struct config_value *next; + char *name; + char *value; + } *values; + char name[0]; + } *sections; +}; + +void config_init(struct config *config); +void config_parse_string(struct config *config, const char *str); +void config_set_value(struct config *config, + const char *section, + const char *name, + const char *value); +const char *config_get_value(struct config *config, + const char *section, + const char *name); + #ifdef HAVE_OVERLAY_XVLIB -cairo_surface_t *x11_overlay_create(enum position pos, int *width, int *height); +cairo_surface_t *x11_overlay_create(struct config *config, int *width, int *height); void x11_overlay_stop(void); #else -static inline cairo_surface_t *x11_overlay_create(enum position pos, int *width, int *height) { return NULL; } +static inline cairo_surface_t *x11_overlay_create(struct config *config, int *width, int *height) { return NULL; } static inline void x11_overlay_stop(void) { } #endif #ifdef HAVE_OVERLAY_XLIB -cairo_surface_t *x11_window_create(enum position pos, int *width, int *height); +cairo_surface_t *x11_window_create(struct config *config, int *width, int *height); #else -static inline cairo_surface_t *x11_window_create(enum position pos, int *width, int *height) { return NULL; } +static inline cairo_surface_t *x11_window_create(struct config *config, int *width, int *height) { return NULL; } #endif #endif /* OVERLAY_H */ diff --git a/overlay/x11/position.c b/overlay/x11/position.c new file mode 100644 index 00000000..0dcfc8de --- /dev/null +++ b/overlay/x11/position.c @@ -0,0 +1,131 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include +#include +#include + +#include "position.h" +#include "../overlay.h" + +static enum position get_position(struct config *config) +{ + const char *v = config_get_value(config, "window", "position"); + if (v == NULL) + return POS_UNSET; + + if (strcmp(v, "top-left") == 0) + return POS_TOP_LEFT; + + if (strcmp(v, "top-centre") == 0) + return POS_TOP_CENTRE; + + if (strcmp(v, "top-right") == 0) + return POS_TOP_RIGHT; + + if (strcmp(v, "middle-left") == 0) + return POS_MIDDLE_LEFT; + + if (strcmp(v, "middle-centre") == 0) + return POS_MIDDLE_CENTRE; + + if (strcmp(v, "middle-right") == 0) + return POS_MIDDLE_RIGHT; + + if (strcmp(v, "bottom-left") == 0) + return POS_BOTTOM_LEFT; + + if (strcmp(v, "bottom-centre") == 0) + return POS_BOTTOM_CENTRE; + + if (strcmp(v, "bottom-right") == 0) + return POS_BOTTOM_RIGHT; + + return POS_UNSET; +} + +enum position +x11_position(Screen *scr, int width, int height, + struct config *config, + int *x, int *y, int *w, int *h) +{ + enum position position = POS_UNSET; + const char *geometry; + + *x = *y = 0; + *w = width; + *h = height; + + geometry = config_get_value(config, "window", "geometry"); + if (geometry) { + sscanf(geometry, "%dx%d+%d+%d", w, h, x, y); + if (*w < width) + *w = width; + if (*h < height) + *h = height; + } else { + position = get_position(config); + if (position != POS_UNSET) { + if (width == -1) { + *w = scr->width; + switch (position & 7) { + default: + case 0: + case 2: *w >>= 1; break; + } + } else if (width > scr->width) { + *w = scr->width; + } else + *w = width; + + if (height == -1) { + *h = scr->height; + switch ((position >> 4) & 7) { + default: + case 0: + case 2: *h >>= 1; break; + } + } else if (height > scr->height) + *h = scr->height; + else + *h = height; + + switch (position & 7) { + default: + case 0: *x = 0; break; + case 1: *x = (scr->width - *w)/2; break; + case 2: *x = scr->width - *w; break; + } + + switch ((position >> 4) & 7) { + default: + case 0: *y = 0; break; + case 1: *y = (scr->height - *h)/2; break; + case 2: *y = scr->height - *h; break; + } + } + } + + return position; +} diff --git a/overlay/x11/position.h b/overlay/x11/position.h new file mode 100644 index 00000000..6221109f --- /dev/null +++ b/overlay/x11/position.h @@ -0,0 +1,38 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#ifndef X11_POSITION_H +#define X11_POSITION_H + +#include + +struct config; +enum position; + +enum position +x11_position(Screen *scr, int width, int height, + struct config *config, + int *x, int *y, int *w, int *h); + +#endif /* X11_POSITION_H */ diff --git a/overlay/x11/x11-overlay.c b/overlay/x11/x11-overlay.c index c2693d38..f57bd55d 100644 --- a/overlay/x11/x11-overlay.c +++ b/overlay/x11/x11-overlay.c @@ -38,6 +38,7 @@ #include #include "../overlay.h" #include "dri2.h" +#include "position.h" #include "rgb2yuv.h" #ifndef ALIGN @@ -142,7 +143,7 @@ static void x11_overlay_destroy(void *data) } cairo_surface_t * -x11_overlay_create(enum position position, int *width, int *height) +x11_overlay_create(struct config *config, int *width, int *height) { Display *dpy; Screen *scr; @@ -152,11 +153,12 @@ x11_overlay_create(enum position position, int *width, int *height) struct drm_i915_gem_mmap_gtt map; struct x11_overlay *priv; unsigned int count, i, j; - int fd, w, h; + int fd, x, y, w, h; XvAdaptorInfo *info; XvImage *image; XvPortID port = -1; void *ptr, *mem; + enum position position; dpy = XOpenDisplay(NULL); if (dpy == NULL) @@ -195,29 +197,7 @@ x11_overlay_create(enum position position, int *width, int *height) XSetErrorHandler(noop); - if (*width == -1) { - w = scr->width; - switch (position & 7) { - default: - case 0: - case 2: w >>= 1; break; - } - } else if (*width > scr->width) { - w = scr->width; - } else - w = *width; - - if (*height == -1) { - h = scr->height; - switch ((position >> 4) & 7) { - default: - case 0: - case 2: h >>= 1; break; - } - } else if (*height > scr->height) - h = scr->height; - else - h = *height; + position = x11_position(scr, *width, *height, config, &x, &y, &w, &h); image = XvCreateImage(dpy, port, FOURCC_RGB565, NULL, w, h); if (image == NULL) @@ -308,18 +288,22 @@ x11_overlay_create(enum position position, int *width, int *height) priv->name = flink.name; priv->visible = false; - switch (position & 7) { - default: - case 0: priv->x = 0; break; - case 1: priv->x = (scr->width - image->width)/2; break; - case 2: priv->x = scr->width - image->width; break; - } + priv->x = x; + priv->y = y; + if (position != POS_UNSET) { + switch (position & 7) { + default: + case 0: priv->x = 0; break; + case 1: priv->x = (scr->width - image->width)/2; break; + case 2: priv->x = scr->width - image->width; break; + } - switch ((position >> 4) & 7) { - default: - case 0: priv->y = 0; break; - case 1: priv->y = (scr->height - image->height)/2; break; - case 2: priv->y = scr->height - image->height; break; + switch ((position >> 4) & 7) { + default: + case 0: priv->y = 0; break; + case 1: priv->y = (scr->height - image->height)/2; break; + case 2: priv->y = scr->height - image->height; break; + } } diff --git a/overlay/x11/x11-window.c b/overlay/x11/x11-window.c index b77f5375..7f7d6d72 100644 --- a/overlay/x11/x11-window.c +++ b/overlay/x11/x11-window.c @@ -32,6 +32,7 @@ #include #include "../overlay.h" +#include "position.h" struct x11_window { struct overlay base; @@ -109,7 +110,7 @@ static void x11_window_destroy(void *data) } cairo_surface_t * -x11_window_create(enum position position, int *width, int *height) +x11_window_create(struct config *config, int *width, int *height) { Display *dpy; Screen *scr; @@ -129,43 +130,7 @@ x11_window_create(enum position position, int *width, int *height) XSetErrorHandler(noop); - if (*width == -1) { - w = scr->width; - switch (position & 7) { - default: - case 0: - case 2: w >>= 1; break; - } - } else if (*width > scr->width) { - w = scr->width; - } else - w = *width; - - if (*height == -1) { - h = scr->height; - switch ((position >> 4) & 7) { - default: - case 0: - case 2: h >>= 1; break; - } - } else if (*height > scr->height) - h = scr->height; - else - h = *height; - - switch (position & 7) { - default: - case 0: x = 0; break; - case 1: x = (scr->width - w)/2; break; - case 2: x = scr->width - w; break; - } - - switch ((position >> 4) & 7) { - default: - case 0: y = 0; break; - case 1: y = (scr->height - h)/2; break; - case 2: y = scr->height - h; break; - } + x11_position(scr, *width, *height, config, &x, &y, &w, &h); attr.override_redirect = True; win = XCreateWindow(dpy, DefaultRootWindow(dpy), -- cgit v1.2.3