1/* 2 * Copyright © 2019 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#include <stdio.h> 25#include <string.h> 26#include <stdlib.h> 27#include <string.h> 28#include <errno.h> 29 30#include "overlay_params.h" 31 32#include "util/os_socket.h" 33 34static enum overlay_param_position 35parse_position(const char *str) 36{ 37 if (!str || !strcmp(str, "top-left")) 38 return LAYER_POSITION_TOP_LEFT; 39 if (!strcmp(str, "top-right")) 40 return LAYER_POSITION_TOP_RIGHT; 41 if (!strcmp(str, "bottom-left")) 42 return LAYER_POSITION_BOTTOM_LEFT; 43 if (!strcmp(str, "bottom-right")) 44 return LAYER_POSITION_BOTTOM_RIGHT; 45 return LAYER_POSITION_TOP_LEFT; 46} 47 48static FILE * 49parse_output_file(const char *str) 50{ 51 return fopen(str, "w+"); 52} 53 54static int 55parse_control(const char *str) 56{ 57 int ret = os_socket_listen_abstract(str, 1); 58 if (ret < 0) { 59 fprintf(stderr, "ERROR: Couldn't create socket pipe at '%s'\n", str); 60 fprintf(stderr, "ERROR: '%s'\n", strerror(errno)); 61 return ret; 62 } 63 64 os_socket_block(ret, false); 65 66 return ret; 67} 68 69static uint32_t 70parse_fps_sampling_period(const char *str) 71{ 72 return strtol(str, NULL, 0) * 1000; 73} 74 75static bool 76parse_no_display(const char *str) 77{ 78 return strtol(str, NULL, 0) != 0; 79} 80 81static unsigned 82parse_unsigned(const char *str) 83{ 84 return strtol(str, NULL, 0); 85} 86 87#define parse_width(s) parse_unsigned(s) 88#define parse_height(s) parse_unsigned(s) 89 90static bool 91parse_help(const char *str) 92{ 93 fprintf(stderr, "Layer params using VK_LAYER_MESA_OVERLAY_CONFIG=\n"); 94#define OVERLAY_PARAM_BOOL(name) \ 95 fprintf(stderr, "\t%s=0|1\n", #name); 96#define OVERLAY_PARAM_CUSTOM(name) 97 OVERLAY_PARAMS 98#undef OVERLAY_PARAM_BOOL 99#undef OVERLAY_PARAM_CUSTOM 100 fprintf(stderr, "\tposition=top-left|top-right|bottom-left|bottom-right\n"); 101 fprintf(stderr, "\tfps_sampling_period=number-of-milliseconds\n"); 102 fprintf(stderr, "\tno_display=0|1\n"); 103 fprintf(stderr, "\toutput_file=/path/to/output.txt\n"); 104 fprintf(stderr, "\twidth=width-in-pixels\n"); 105 fprintf(stderr, "\theight=height-in-pixels\n"); 106 107 return true; 108} 109 110static bool is_delimiter(char c) 111{ 112 return c == 0 || c == ',' || c == ':' || c == ';' || c == '='; 113} 114 115static int 116parse_string(const char *s, char *out_param, char *out_value) 117{ 118 int i = 0; 119 120 for (; !is_delimiter(*s); s++, out_param++, i++) 121 *out_param = *s; 122 123 *out_param = 0; 124 125 if (*s == '=') { 126 s++; 127 i++; 128 for (; !is_delimiter(*s); s++, out_value++, i++) 129 *out_value = *s; 130 } else 131 *(out_value++) = '1'; 132 *out_value = 0; 133 134 if (*s && is_delimiter(*s)) { 135 s++; 136 i++; 137 } 138 139 if (*s && !i) { 140 fprintf(stderr, "mesa-overlay: syntax error: unexpected '%c' (%i) while " 141 "parsing a string\n", *s, *s); 142 fflush(stderr); 143 } 144 145 return i; 146} 147 148const char *overlay_param_names[] = { 149#define OVERLAY_PARAM_BOOL(name) #name, 150#define OVERLAY_PARAM_CUSTOM(name) 151 OVERLAY_PARAMS 152#undef OVERLAY_PARAM_BOOL 153#undef OVERLAY_PARAM_CUSTOM 154}; 155 156void 157parse_overlay_env(struct overlay_params *params, 158 const char *env) 159{ 160 uint32_t num; 161 char key[256], value[256]; 162 163 memset(params, 0, sizeof(*params)); 164 165 /* Visible by default */ 166 params->enabled[OVERLAY_PARAM_ENABLED_fps] = true; 167 params->enabled[OVERLAY_PARAM_ENABLED_frame_timing] = true; 168 params->enabled[OVERLAY_PARAM_ENABLED_device] = true; 169 params->enabled[OVERLAY_PARAM_ENABLED_format] = true; 170 params->fps_sampling_period = 500000; /* 500ms */ 171 params->width = params->height = 300; 172 params->control = -1; 173 174 if (!env) 175 return; 176 177 while ((num = parse_string(env, key, value)) != 0) { 178 env += num; 179 180#define OVERLAY_PARAM_BOOL(name) \ 181 if (!strcmp(#name, key)) { \ 182 params->enabled[OVERLAY_PARAM_ENABLED_##name] = \ 183 strtol(value, NULL, 0); \ 184 continue; \ 185 } 186#define OVERLAY_PARAM_CUSTOM(name) \ 187 if (!strcmp(#name, key)) { \ 188 params->name = parse_##name(value); \ 189 continue; \ 190 } 191 OVERLAY_PARAMS 192#undef OVERLAY_PARAM_BOOL 193#undef OVERLAY_PARAM_CUSTOM 194 fprintf(stderr, "Unknown option '%s'\n", key); 195 } 196} 197