mightymandel v16

GPU-based Mandelbrot set explorer

startup.c
Go to the documentation of this file.
1 // mightymandel -- GPU-based Mandelbrot Set explorer
2 // Copyright (C) 2012,2013,2014,2015 Claude Heiland-Allen
3 // License GPL3+ http://www.gnu.org/licenses/gpl.html
4 
5 #include <math.h>
6 #include <stdbool.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 
11 #include "logging.h"
12 #include "parse.h"
13 #include "utility.h"
14 #include "startup.h"
15 #include "version.h"
16 #include "config.glsl"
17 
18 void print_version(void) {
19  printf("%s\n", mightymandel_version);
20 }
21 
22 void print_banner(void) {
23  log_message(LOG_INFO, "mightymandel -- GPU-based Mandelbrot Set explorer\n");
24  log_message(LOG_INFO, "Copyright (C) 2012,2013,2014,2015 Claude Heiland-Allen\n");
25  log_message(LOG_INFO, "License GPL3+ http://www.gnu.org/licenses/gpl.html\n");
26  log_message(LOG_INFO, "Version %s\n", mightymandel_version);
27 }
28 
29 void print_usage(const char *progname) {
30  printf("%s [argument]* [filename]\n", progname);
31  printf("Arguments:\n");
32  printf("\n");
33  printf(" --help show this usage message and exit\n");
34  printf(" --version show the version string and exit\n");
35  printf("\n");
36  printf(" --view X Y R set view coordinates to X + i Y @ R\n");
37  printf("\n");
38  printf(" --verbose level set the log message verbosity\n");
39  printf(" valid levels (from quiet to noisy) are:\n");
40  printf(" fatal error warn notice info debug\n");
41  printf(" --geometry WxH set window size (default --size)\n");
42  printf(" --size WxH set image size (default --geometry)\n");
43  printf(" --de compute distance estimates (default)\n");
44  printf(" --no-de don't compute distance estimates\n");
45  printf(" --no-approx don't compute series approximation\n");
46  printf(" sometimes that optimisation breaks glitch fixing\n");
47  printf("\n");
48  printf(" --weight W how dark to make the boundary (default 0.0)\n");
49  printf(" --glitch highlight glitches in ugly colours\n");
50  printf(" --no-glitch try to mask glitches (default)\n");
51  printf(" --max-glitch G percentage of glitches allowed (default 0.02)\n");
52  printf(" lower value gives better image at higher cost\n");
53  printf(" --max-blob B maximum pixels in glitched blob allowed (default 1)\n");
54  printf(" lower value gives better image at higher cost\n");
55  printf(" --sharpness S how sharp to make visible interior (default 0.01)\n");
56  printf(" lower value gives better image at higher cost\n");
57  printf(" --timeout T timeout after T seconds (default infinity)\n");
58  printf(" --slice S split calculations into 4^S blocks\n");
59  printf(" valid range from 0 (default) to %d\n", SLICE_MAX);
60  printf("\n");
61  printf(" --interactive start in interactive mode (default)\n");
62  printf(" --one-shot render one image and exit\n");
63  printf(" --tile N[xM] render a large image as NxM tiles\n");
64  printf(" M defaults to N if it isn't specified\n");
65  printf(" final image size is (W*N)x(H*M)\n");
66  printf(" --zoom F render a zoom-in sequence of F frames\n");
67  printf(" can be combined with --tile\n");
68  printf(" --overhead quit after startup without rendering anything\n");
69  printf(" might be useful for benchmarking\n");
70  printf("\n");
71  printf("Only use at most one of: --interactive --one-shot (--tile --zoom)\n");
72  printf("\n");
73  printf("If a filename argument is given, it will be loaded to set the\n");
74  printf("viewing parameters.\n");
75 }
76 
77 bool parse_command_line(struct options *options, int argc, char **argv) {
78 #define O(flag) (0 == strcmp((flag), argv[i]) && strlen((flag)) == strlen(argv[i]))
79 #define NEXT do{ i++; if (! (i < argc)) { log_message(LOG_FATAL, "%s: argument expected\n", argv[i-1]); return false; } }while(0)
80 #define NEXT2(s) do{ i++; if (! (i < argc)) { log_message(LOG_FATAL, "%s: argument expected\n", s); return false; } }while(0)
81  for (int i = 1; i < argc; ++i) {
82  if (false) {
83  } else if (O("-h") || O("-?") || O("-help") || O("--help")) {
84  options->help = true;
85  return true;
86  } else if (O("-v") || O("-V") || O("-version") || O("--version")) {
87  options->version = true;
88  return true;
89  } else if (O("--view")) {
90  NEXT2("--view");
91  const char *sx = argv[i];
92  NEXT2("--view");
93  const char *sy = argv[i];
94  NEXT2("--view");
95  const char *sz = argv[i];
96  mpfr_init2(options->radius, 53);
97  mpfr_set_str(options->radius, sz, 10, MPFR_RNDN);
98  if (! (mpfr_regular_p(options->radius) && mpfr_sgn(options->radius) > 0)) {
99  log_message(LOG_FATAL, "--view: invalid radius: %s\n", sz);
100  return false;
101  }
102  mpfr_prec_t bits = precision_for_radius(options->radius);
103  mpfr_init2(options->centerx, bits);
104  mpfr_init2(options->centery, bits);
105  mpfr_set_str(options->centerx, sx, 10, MPFR_RNDN);
106  mpfr_set_str(options->centery, sy, 10, MPFR_RNDN);
107  options->view_supplied = true;
108  } else if (O("--verbose")) {
109  NEXT;
110  if (false) {
111  } else if (O("fatal" )) { options->log_level = LOG_FATAL;
112  } else if (O("error" )) { options->log_level = LOG_ERROR;
113  } else if (O("warn" )) { options->log_level = LOG_WARN;
114  } else if (O("notice")) { options->log_level = LOG_NOTICE;
115  } else if (O("info" )) { options->log_level = LOG_INFO;
116  } else if (O("debug" )) { options->log_level = LOG_DEBUG;
117  } else {
118  log_message(LOG_FATAL, "--verbose: invalid level: %s\n", argv[i]);
119  log_message(LOG_NOTICE, "--verbose: valid levels: fatal error warn notice info debug\n");
120  return false;
121  }
122  } else if (O("--de")) {
123  options->render_de = true;
124  } else if (O("-no-de") || O("--no-de")) {
125  if (O("-no-de")) {
126  log_message(LOG_WARN, "deprecated: -no-de use --no-de instead\n");
127  }
128  options->render_de = false;
129  } else if (O("--no-approx")) {
130  options->series_approx = false;
131  } else if (O("-glitch") || O("--glitch")) {
132  if (O("-glitch")) {
133  log_message(LOG_WARN, "deprecated: -glitch use --glitch instead\n");
134  }
135  options->show_glitches = true;
136  } else if (O("--no-glitch")) {
137  options->show_glitches = false;
138  } else if (O("--interactive")) {
139  options->interactive = true;
140  } else if (O("-bench") || O("--one-shot")) {
141  if (O("-bench")) {
142  log_message(LOG_WARN, "deprecated: -bench use --one-shot instead\n");
143  }
144  options->oneshot = true;
145  } else if (O("-tile") || O("--tile")) {
146  if (O("-tile")) {
147  log_message(LOG_WARN, "deprecated: -tile use --tile instead\n");
148  }
149  options->tile = true;
150  NEXT;
151  if (strchr(argv[i], 'x')) {
152  int tile_width = 0;
153  int tile_height = 0;
154  if (! (2 == sscanf(argv[i], "%dx%d", &tile_width, &tile_height))) {
155  log_message(LOG_FATAL, "--tile: invalid dimensions: %s\n", argv[i]);
156  return false;
157  }
158  if (! (tile_width > 0 && tile_height > 0)) {
159  log_message(LOG_FATAL, "--tile: dimensions must be positive: %s\n", argv[i]);
160  return false;
161  }
162  options->tile_width = tile_width;
163  options->tile_height = tile_height;
164  } else {
165  int tile_count = atoi(argv[i]);
166  if (! (tile_count > 0)) {
167  log_message(LOG_FATAL, "--tile: dimension must be positive: %s\n", argv[i]);
168  return false;
169  }
170  options->tile_width = tile_count;
171  options->tile_height = tile_count;
172  }
173  } else if (O("-zoom") || O("--zoom")) {
174  if (O("-zoom")) {
175  log_message(LOG_WARN, "deprecated: -zoom use --zoom instead\n");
176  }
177  options->zoom = true;
178  NEXT;
179  int zoom_frames = atoi(argv[i]);
180  if (! (zoom_frames > 0)) {
181  log_message(LOG_FATAL, "--zoom: frame count must be positive: %s\n", argv[i]);
182  return false;
183  }
184  options->zoom_frames = zoom_frames;
185  } else if (O("--overhead")) {
186  options->overhead = true;
187  } else if (O("--geometry")) {
188  NEXT;
189  int width = 0;
190  int height = 0;
191  if (! (2 == sscanf(argv[i], "%dx%d", &width, &height))) {
192  log_message(LOG_FATAL, "--size: invalid dimensions: %s\n", argv[i]);
193  return false;
194  }
195  if (! (width > 0 && height > 0)) {
196  log_message(LOG_FATAL, "--size: dimensions must be positive: %s\n", argv[i]);
197  return false;
198  }
199  options->geometry = true;
200  options->win_width = width;
201  options->win_height = height;
202  } else if (O("-size") || O("--size")) {
203  if (O("-size")) {
204  log_message(LOG_WARN, "deprecated: -size use --size instead\n");
205  }
206  NEXT;
207  int width = 0;
208  int height = 0;
209  if (! (2 == sscanf(argv[i], "%dx%d", &width, &height))) {
210  log_message(LOG_FATAL, "--size: invalid dimensions: %s\n", argv[i]);
211  return false;
212  }
213  if (! (width > 0 && height > 0)) {
214  log_message(LOG_FATAL, "--size: dimensions must be positive: %s\n", argv[i]);
215  return false;
216  }
217  options->size = true;
218  options->width = width;
219  options->height = height;
220  } else if (O("-weight") || O("--weight")) {
221  if (O("-weight")) {
222  log_message(LOG_WARN, "deprecated: -weight use --weight instead\n");
223  }
224  NEXT;
225  options->weight = atof(argv[i]);
226  } else if (O("--max-glitch")) {
227  NEXT;
228  options->max_glitch = fmin(fmax(atof(argv[i]), 0.0), 100.0);
229  } else if (O("--max-blob")) {
230  NEXT;
231  options->max_blob = max(atoi(argv[i]), 0);
232  } else if (O("--sharpness")) {
233  NEXT;
234  options->sharpness = fmin(fmax(atof(argv[i]), 0.0), 1.0);
235  } else if (O("--timeout")) {
236  NEXT;
237  options->timeout = atof(argv[i]);
238  } else if (O("--slice")) {
239  NEXT;
240  options->slice = min(max(atoi(argv[i]), 0), SLICE_MAX);
241  } else if (! options->file_to_load) {
242  options->file_to_load = argv[i];
243  } else {
244  log_message(LOG_FATAL, "unexpected argument: \n", argv[i]);
245  return false;
246  }
247  }
248  return true;
249 #undef O
250 #undef NEXT
251 #undef NEXT2
252 }