1 /* Test retrieving and settings possible modes. */
2 #include <allegro5/allegro.h>
3 #include <allegro5/allegro_font.h>
4 #include <allegro5/allegro_primitives.h>
5 #include <stdio.h>
6 
7 #include "common.c"
8 
9 ALLEGRO_FONT *font;
10 ALLEGRO_COLOR white;
11 int font_h;
12 int modes_count;
13 int options_count;
14 char status[256];
15 int flags, old_flags;
16 
17 int visible_rows;
18 int first_visible_row;
19 
20 int selected_column;
21 int selected_mode;
22 int selected_option;
23 
24 #define X(x, m) {#x, ALLEGRO_##x, 0, m, 0}
25 struct {
26     char const *name;
27     int option;
28     int value, max_value;
29     int required;
30 } options[] = {
31     X(COLOR_SIZE, 32),
32     X(RED_SIZE, 8),
33     X(GREEN_SIZE, 8),
34     X(BLUE_SIZE, 8),
35     X(ALPHA_SIZE, 8),
36     X(RED_SHIFT, 32),
37     X(GREEN_SHIFT, 32),
38     X(BLUE_SHIFT, 32),
39     X(ALPHA_SHIFT, 32),
40     X(DEPTH_SIZE, 32),
41     X(FLOAT_COLOR, 1),
42     X(FLOAT_DEPTH, 1),
43     X(STENCIL_SIZE, 32),
44     X(SAMPLE_BUFFERS, 1),
45     X(SAMPLES, 8),
46     X(RENDER_METHOD, 2),
47     X(SINGLE_BUFFER, 1),
48     X(SWAP_METHOD, 1),
49     X(VSYNC, 2),
50     X(COMPATIBLE_DISPLAY, 1),
51     X(MAX_BITMAP_SIZE, 65536),
52     X(SUPPORT_NPOT_BITMAP, 1),
53     X(CAN_DRAW_INTO_BITMAP, 1),
54     X(SUPPORT_SEPARATE_ALPHA, 1),
55 };
56 #undef X
57 static char const *flag_names[32];
init_flags(void)58 static void init_flags(void)
59 {
60    int i;
61    #define X(f) if (1 << i == ALLEGRO_##f) flag_names[i] = #f;
62    for (i = 0; i < 32; i++) {
63       X(WINDOWED)
64       X(FULLSCREEN)
65       X(OPENGL)
66       X(RESIZABLE)
67       X(FRAMELESS)
68       X(GENERATE_EXPOSE_EVENTS)
69       X(FULLSCREEN_WINDOW)
70       X(MINIMIZED)
71    }
72    #undef X
73 }
74 
load_font(void)75 static void load_font(void)
76 {
77    font = al_create_builtin_font();
78    if (!font) {
79       abort_example("Error creating builtin font\n");
80    }
81    font_h = al_get_font_line_height(font);
82 }
83 
display_options(ALLEGRO_DISPLAY * display)84 static void display_options(ALLEGRO_DISPLAY *display)
85 {
86    int i, y = 10;
87    int x = 10;
88    int n = options_count;
89    int dw = al_get_display_width(display);
90    int dh = al_get_display_height(display);
91    ALLEGRO_COLOR c;
92 
93    modes_count = al_get_num_display_modes();
94 
95    c = al_map_rgb_f(0.8, 0.8, 1);
96    al_draw_textf(font, c, x, y, 0, "Create new display");
97    y += font_h;
98    for (i = first_visible_row; i < modes_count + 2 &&
99       i < first_visible_row + visible_rows; i++) {
100       ALLEGRO_DISPLAY_MODE mode;
101       if (i > 1) {
102          al_get_display_mode(i - 2, &mode);
103       }
104       else if (i == 1) {
105          mode.width = 800;
106          mode.height = 600;
107          mode.format = 0;
108          mode.refresh_rate = 0;
109       }
110       else {
111          mode.width = 800;
112          mode.height = 600;
113          mode.format = 0;
114          mode.refresh_rate = 0;
115       }
116       if (selected_column == 0 && selected_mode == i) {
117          c = al_map_rgb_f(1, 1, 0);
118          al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
119          al_draw_filled_rectangle(x, y, x + 300, y + font_h, c);
120       }
121       c = al_map_rgb_f(0, 0, 0);
122       al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
123       if ((i == first_visible_row && i > 0) ||
124             (i == first_visible_row + visible_rows - 1 &&
125             i < modes_count + 1)) {
126          al_draw_textf(font, c, x, y, 0, "...");
127       }
128       else {
129          al_draw_textf(font, c, x, y, 0, "%s %d x %d (fmt: %x, %d Hz)",
130             i > 1 ? "Fullscreen" : i == 0 ? "Windowed" : "FS Window",
131             mode.width, mode.height, mode.format, mode.refresh_rate);
132       }
133       y += font_h;
134    }
135 
136    x = dw / 2 + 10;
137    y = 10;
138    c = al_map_rgb_f(0.8, 0.8, 1);
139    al_draw_textf(font, c, x, y, 0, "Options for new display");
140    al_draw_textf(font, c, dw - 10, y, ALLEGRO_ALIGN_RIGHT, "(current display)");
141    y += font_h;
142    for (i = 0; i < n; i++) {
143       if (selected_column == 1 && selected_option == i) {
144          c = al_map_rgb_f(1, 1, 0);
145          al_draw_filled_rectangle(x, y, x + 300, y + font_h, c);
146       }
147 
148       switch (options[i].required) {
149          case ALLEGRO_REQUIRE: c = al_map_rgb_f(0.5, 0, 0); break;
150          case ALLEGRO_SUGGEST: c = al_map_rgb_f(0, 0, 0); break;
151          case ALLEGRO_DONTCARE: c = al_map_rgb_f(0.5, 0.5, 0.5); break;
152       }
153       al_draw_textf(font, c, x, y, 0, "%s: %d (%s)", options[i].name,
154          options[i].value,
155             options[i].required == ALLEGRO_REQUIRE ? "required" :
156             options[i].required == ALLEGRO_SUGGEST ? "suggested" :
157             "ignored");
158 
159       c = al_map_rgb_f(0.9, 0.5, 0.3);
160       al_draw_textf(font, c, dw - 10, y, ALLEGRO_ALIGN_RIGHT, "%d",
161          al_get_display_option(display, options[i].option));
162       y += font_h;
163    }
164 
165    c = al_map_rgb_f(0, 0, 0.8);
166    x = 10;
167    y = dh - font_h - 10;
168    y -= font_h;
169    al_draw_textf(font, c, x, y, 0, "PageUp/Down: modify values");
170    y -= font_h;
171    al_draw_textf(font, c, x, y, 0, "Return: set mode or require option");
172    y -= font_h;
173    al_draw_textf(font, c, x, y, 0, "Cursor keys: change selection");
174 
175    y -= font_h * 2;
176    for (i = 0; i < 32; i++) {
177       if (flag_names[i]) {
178          if (flags & (1 << i)) c = al_map_rgb_f(0.5, 0, 0);
179          else if (old_flags & (1 << i)) c = al_map_rgb_f(0.5, 0.4, 0.4);
180          else continue;
181          al_draw_text(font, c, x, y, 0, flag_names[i]);
182          x += al_get_text_width(font, flag_names[i]) + 10;
183       }
184    }
185 
186    c = al_map_rgb_f(1, 0, 0);
187    al_draw_text(font, c, dw / 2, dh - font_h, ALLEGRO_ALIGN_CENTRE, status);
188 }
189 
update_ui(void)190 static void update_ui(void)
191 {
192    int h = al_get_display_height(al_get_current_display());
193    visible_rows = h / font_h - 10;
194 }
195 
main(int argc,char ** argv)196 int main(int argc, char **argv)
197 {
198    ALLEGRO_DISPLAY *display;
199    ALLEGRO_EVENT_QUEUE *queue;
200    ALLEGRO_TIMER *timer;
201    bool redraw = false;
202 
203    (void)argc;
204    (void)argv;
205 
206    if (!al_init()) {
207       abort_example("Could not init Allegro.\n");
208    }
209    init_flags();
210    al_init_primitives_addon();
211 
212    white = al_map_rgba_f(1, 1, 1, 1);
213 
214    al_install_keyboard();
215    al_install_mouse();
216    al_init_font_addon();
217 
218    display = al_create_display(800, 600);
219    if (!display) {
220       abort_example("Could not create display.\n");
221    }
222 
223    load_font();
224 
225    timer = al_create_timer(1.0 / 60);
226 
227    modes_count = al_get_num_display_modes();
228    options_count = sizeof(options) / sizeof(options[0]);
229 
230    update_ui();
231 
232    al_clear_to_color(al_map_rgb_f(1, 1, 1));
233    display_options(display);
234    al_flip_display();
235 
236    queue = al_create_event_queue();
237    al_register_event_source(queue, al_get_keyboard_event_source());
238    al_register_event_source(queue, al_get_mouse_event_source());
239    al_register_event_source(queue, al_get_display_event_source(display));
240    al_register_event_source(queue, al_get_timer_event_source(timer));
241 
242    al_start_timer(timer);
243 
244    while (1) {
245       ALLEGRO_EVENT event;
246       al_wait_for_event(queue, &event);
247       if (event.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
248          break;
249       }
250       if (event.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN) {
251          if (event.mouse.button == 1) {
252             int dw = al_get_display_width(display);
253             int y = 10;
254             int row = (event.mouse.y - y) / font_h - 1;
255             int column = event.mouse.x / (dw / 2);
256             if (column == 0) {
257                if (row >= 0 && row <= modes_count) {
258                   selected_column = column;
259                   selected_mode = row;
260                   redraw = true;
261                }
262             }
263             if (column == 1) {
264                if (row >= 0 && row < options_count) {
265                   selected_column = column;
266                   selected_option = row;
267                   redraw = true;
268                }
269             }
270          }
271       }
272       if (event.type == ALLEGRO_EVENT_TIMER) {
273           int f = al_get_display_flags(display);
274           if (f != flags) {
275               redraw = true;
276               flags = f;
277               old_flags |= f;
278           }
279       }
280       if (event.type == ALLEGRO_EVENT_KEY_CHAR) {
281          int change;
282          if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE)
283             break;
284          if (event.keyboard.keycode == ALLEGRO_KEY_LEFT) {
285             selected_column = 0;
286             redraw = true;
287          }
288          if (event.keyboard.keycode == ALLEGRO_KEY_RIGHT) {
289             selected_column = 1;
290             redraw = true;
291          }
292          if (event.keyboard.keycode == ALLEGRO_KEY_UP) {
293             if (selected_column == 0) selected_mode -= 1;
294             if (selected_column == 1) selected_option -= 1;
295             redraw = true;
296          }
297          if (event.keyboard.keycode == ALLEGRO_KEY_DOWN) {
298             if (selected_column == 0) selected_mode += 1;
299             if (selected_column == 1) selected_option += 1;
300             redraw = true;
301          }
302          if (event.keyboard.keycode == ALLEGRO_KEY_ENTER) {
303              if (selected_column == 0) {
304                 ALLEGRO_DISPLAY_MODE mode;
305                 ALLEGRO_DISPLAY *new_display;
306                 if (selected_mode > 1) {
307                     al_get_display_mode(selected_mode - 2, &mode);
308                     al_set_new_display_flags(ALLEGRO_FULLSCREEN);
309                 }
310                 else if (selected_mode == 1) {
311                     mode.width = 800;
312                     mode.height = 600;
313                     al_set_new_display_flags(ALLEGRO_FULLSCREEN_WINDOW);
314                 }
315                 else {
316                     mode.width = 800;
317                     mode.height = 600;
318                     al_set_new_display_flags(ALLEGRO_WINDOWED);
319                 }
320 
321                 al_destroy_font(font);
322                 font = NULL;
323 
324                 new_display = al_create_display(
325                    mode.width, mode.height);
326                 if (new_display) {
327                    al_destroy_display(display);
328                    display = new_display;
329                    al_set_target_backbuffer(display);
330                    al_register_event_source(queue,
331                       al_get_display_event_source(display));
332                    update_ui();
333                    sprintf(status, "Display creation succeeded.");
334                 }
335                 else {
336                    sprintf(status, "Display creation failed.");
337                 }
338 
339                 load_font();
340              }
341              if (selected_column == 1) {
342                  options[selected_option].required += 1;
343                  options[selected_option].required %= 3;
344                  al_set_new_display_option(
345                     options[selected_option].option,
346                     options[selected_option].value,
347                     options[selected_option].required);
348              }
349              redraw = true;
350          }
351          change = 0;
352          if (event.keyboard.keycode == ALLEGRO_KEY_PGUP) change = 1;
353          if (event.keyboard.keycode == ALLEGRO_KEY_PGDN) change = -1;
354          if (change && selected_column == 1) {
355             options[selected_option].value += change;
356             if (options[selected_option].value < 0)
357                options[selected_option].value = 0;
358             if (options[selected_option].value >
359                options[selected_option].max_value)
360                options[selected_option].value =
361                   options[selected_option].max_value;
362             al_set_new_display_option(options[selected_option].option,
363                options[selected_option].value,
364                options[selected_option].required);
365             redraw = true;
366          }
367       }
368 
369       if (selected_mode < 0) selected_mode = 0;
370       if (selected_mode > modes_count + 1)
371          selected_mode = modes_count + 1;
372       if (selected_option < 0) selected_option = 0;
373       if (selected_option >= options_count)
374          selected_option = options_count - 1;
375       if (selected_mode < first_visible_row)
376          first_visible_row = selected_mode;
377       if (selected_mode > first_visible_row + visible_rows - 1)
378          first_visible_row = selected_mode - visible_rows + 1;
379 
380       if (redraw && al_is_event_queue_empty(queue)) {
381          redraw = false;
382          al_clear_to_color(al_map_rgb_f(1, 1, 1));
383          display_options(display);
384          al_flip_display();
385       }
386    }
387 
388    al_destroy_font(font);
389 
390    return 0;
391 }
392 
393 /* vim: set sts=3 sw=3 et: */
394