1 /*
2  *       Example program for the Allegro library.
3  *
4  *       From left to right you should see Red, Green, Blue gradients.
5  */
6 
7 #define ALLEGRO_UNSTABLE
8 #include "allegro5/allegro.h"
9 
10 #include "common.c"
11 
12 enum Mode
13 {
14    MODE_VIDEO,
15    MODE_MEMORY,
16    MODE_BACKBUFFER
17 };
18 
fill(ALLEGRO_BITMAP * bitmap,int lock_flags)19 static void fill(ALLEGRO_BITMAP *bitmap, int lock_flags)
20 {
21    ALLEGRO_LOCKED_REGION *locked;
22    uint8_t *ptr;
23    int i, j;
24 
25    /* Locking the bitmap means, we work directly with pixel data.  We can
26     * choose the format we want to work with, which may imply conversions, or
27     * use the bitmap's actual format so we can work directly with the bitmap's
28     * pixel data.
29     * We use a 16-bit format and odd positions and sizes to increase the
30     * chances of uncovering bugs.
31     */
32    locked = al_lock_bitmap_region(bitmap, 193, 65, 3*127, 127,
33       ALLEGRO_PIXEL_FORMAT_RGB_565, lock_flags);
34    if (!locked)
35       return;
36 
37    for (j = 0; j < 127; j++) {
38       ptr = (uint8_t *)locked->data + j * locked->pitch;
39 
40       for (i = 0; i < 3*127; i++) {
41          uint8_t red;
42          uint8_t green;
43          uint8_t blue;
44          uint16_t col;
45          uint16_t *cptr = (uint16_t *)ptr;
46 
47          if (j == 0 || j == 126 || i == 0 || i == 3*127-1) {
48             red = green = blue = 0;
49          }
50          else if (i < 127) {
51             red = 255;
52             green = blue = j*2;
53          }
54          else if (i < 2*127) {
55             green = 255;
56             red = blue = j*2;
57          }
58          else {
59             blue = 255;
60             red = green = j*2;
61          }
62 
63          /* The RGB_555 format means, the 16 bits per pixel are laid out like
64           * this, least significant bit right: RRRRR GGGGGG BBBBB
65           * Because the byte order can vary per platform (big endian or
66           * little endian) we encode an integer and store that
67           * directly rather than storing each component separately.
68           *
69           * In READWRITE mode the light blue background should should through
70           * the stipple pattern.
71           */
72          if ((lock_flags & ALLEGRO_LOCK_WRITEONLY) || (j + i) % 2 == 1) {
73             col = ((red/8) << 11) | ((green/4) << 5) | (blue/8);
74             *cptr = col;
75          }
76          ptr += 2;
77       }
78    }
79    al_unlock_bitmap(bitmap);
80 }
81 
draw(ALLEGRO_DISPLAY * display,enum Mode mode,int lock_flags)82 static void draw(ALLEGRO_DISPLAY *display, enum Mode mode, int lock_flags)
83 {
84    ALLEGRO_BITMAP *bitmap;
85 
86    /* Create the bitmap to lock, or use the display backbuffer. */
87    if (mode == MODE_VIDEO) {
88       log_printf("Locking video bitmap");
89       al_clear_to_color(al_map_rgb(0, 0, 0));
90       al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP);
91       bitmap = al_create_bitmap(3*256, 256);
92    }
93    else if (mode == MODE_MEMORY) {
94       log_printf("Locking memory bitmap");
95       al_clear_to_color(al_map_rgb(0, 0, 0));
96       al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP);
97       bitmap = al_create_bitmap(3*256, 256);
98    }
99    else {
100       log_printf("Locking display backbuffer");
101       bitmap = al_get_backbuffer(display);
102    }
103    if (!bitmap) {
104       abort_example("Error creating bitmap");
105    }
106 
107    if (lock_flags & ALLEGRO_LOCK_WRITEONLY) {
108       log_printf(" in write-only mode\n");
109    }
110    else {
111       log_printf(" in read/write mode\n");
112    }
113 
114    al_set_target_bitmap(bitmap);
115    al_clear_to_color(al_map_rgb_f(0.8, 0.8, 0.9));
116    al_set_target_backbuffer(display);
117 
118    fill(bitmap, lock_flags);
119 
120    if (mode != MODE_BACKBUFFER) {
121       al_draw_bitmap(bitmap, 0, 0, 0);
122       al_destroy_bitmap(bitmap);
123       bitmap = NULL;
124    }
125 
126    al_flip_display();
127 }
128 
cycle_mode(enum Mode mode)129 static enum Mode cycle_mode(enum Mode mode)
130 {
131    switch (mode) {
132       case MODE_VIDEO:
133          return MODE_MEMORY;
134       case MODE_MEMORY:
135          return MODE_BACKBUFFER;
136       case MODE_BACKBUFFER:
137       default:
138          return MODE_VIDEO;
139    }
140 }
141 
toggle_writeonly(int lock_flags)142 static int toggle_writeonly(int lock_flags)
143 {
144    return lock_flags ^ ALLEGRO_LOCK_WRITEONLY;
145 }
146 
main(int argc,char ** argv)147 int main(int argc, char **argv)
148 {
149    ALLEGRO_DISPLAY *display;
150    ALLEGRO_EVENT_QUEUE *events;
151    ALLEGRO_EVENT event;
152    enum Mode mode = MODE_VIDEO;
153    int lock_flags = ALLEGRO_LOCK_WRITEONLY;
154    bool redraw = true;
155 
156    (void)argc;
157    (void)argv;
158 
159    if (!al_init()) {
160       abort_example("Could not init Allegro.\n");
161    }
162 
163    al_install_keyboard();
164    al_install_mouse();
165    al_install_touch_input();
166 
167    open_log();
168 
169    /* Create a window. */
170    display = al_create_display(3*256, 256);
171    if (!display) {
172       abort_example("Error creating display\n");
173    }
174 
175    events = al_create_event_queue();
176    al_register_event_source(events, al_get_keyboard_event_source());
177    al_register_event_source(events, al_get_mouse_event_source());
178    if (al_is_touch_input_installed()) {
179       al_register_event_source(events,
180          al_get_touch_input_mouse_emulation_event_source());
181    }
182 
183    log_printf("Press space to change bitmap type\n");
184    log_printf("Press w to toggle WRITEONLY mode\n");
185 
186    for (;;) {
187       if (redraw) {
188          draw(display, mode, lock_flags);
189          redraw = false;
190       }
191 
192       al_wait_for_event(events, &event);
193       if (event.type == ALLEGRO_EVENT_KEY_CHAR) {
194          if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE)
195             break;
196          if (event.keyboard.unichar == ' ') {
197             mode = cycle_mode(mode);
198             redraw = true;
199          }
200          else if (event.keyboard.unichar == 'w' || event.keyboard.unichar == 'W') {
201             lock_flags = toggle_writeonly(lock_flags);
202             redraw = true;
203          }
204       }
205       else if (event.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN) {
206          if (event.mouse.button == 1) {
207             if (event.mouse.x < al_get_display_width(display) / 2) {
208                mode = cycle_mode(mode);
209             }
210             else {
211                lock_flags = toggle_writeonly(lock_flags);
212             }
213             redraw = true;
214          }
215       }
216    }
217 
218    close_log(false);
219    return 0;
220 }
221 
222 /* vim: set sts=3 sw=3 et: */
223