1 /* An example demonstrating different blending modes.
2 */
3 #include <allegro5/allegro.h>
4 #include <allegro5/allegro_font.h>
5 #include <allegro5/allegro_image.h>
6 #include <allegro5/allegro_color.h>
7 #include <stdio.h>
8 #include <stdarg.h>
9 #include <math.h>
10
11 #include "common.c"
12
13 struct Example
14 {
15 ALLEGRO_BITMAP *pattern;
16 ALLEGRO_FONT *font;
17 ALLEGRO_EVENT_QUEUE *queue;
18 ALLEGRO_COLOR background, text, white;
19
20 double timer[4], counter[4];
21 int FPS;
22 float text_x, text_y;
23 } ex;
24
example_bitmap(int w,int h)25 static ALLEGRO_BITMAP *example_bitmap(int w, int h)
26 {
27 int i, j;
28 float mx = w * 0.5;
29 float my = h * 0.5;
30 ALLEGRO_STATE state;
31 ALLEGRO_BITMAP *pattern = al_create_bitmap(w, h);
32 al_store_state(&state, ALLEGRO_STATE_TARGET_BITMAP);
33 al_set_target_bitmap(pattern);
34 al_lock_bitmap(pattern, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_WRITEONLY);
35 for (i = 0; i < w; i++) {
36 for (j = 0; j < h; j++) {
37 float a = atan2(i - mx, j - my);
38 float d = sqrt(pow(i - mx, 2) + pow(j - my, 2));
39 float sat = pow(1.0 - 1 / (1 + d * 0.1), 5);
40 float hue = 3 * a * 180 / ALLEGRO_PI;
41 hue = (hue / 360 - floorf(hue / 360)) * 360;
42 al_put_pixel(i, j, al_color_hsv(hue, sat, 1));
43 }
44 }
45 al_put_pixel(0, 0, al_map_rgb(0, 0, 0));
46 al_unlock_bitmap(pattern);
47 al_restore_state(&state);
48 return pattern;
49 }
50
set_xy(float x,float y)51 static void set_xy(float x, float y)
52 {
53 ex.text_x = x;
54 ex.text_y = y;
55 }
56
get_xy(float * x,float * y)57 static void get_xy(float *x, float *y)
58 {
59 *x = ex.text_x;
60 *y = ex.text_y;
61 }
62
print(char const * format,...)63 static void print(char const *format, ...)
64 {
65 va_list list;
66 char message[1024];
67 int th = al_get_font_line_height(ex.font);
68 va_start(list, format);
69 vsnprintf(message, sizeof message, format, list);
70 va_end(list);
71 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
72 al_draw_textf(ex.font, ex.text, ex.text_x, ex.text_y, 0, "%s", message);
73 ex.text_y += th;
74 }
75
start_timer(int i)76 static void start_timer(int i)
77 {
78 ex.timer[i] -= al_get_time();
79 ex.counter[i]++;
80 }
81
stop_timer(int i)82 static void stop_timer(int i)
83 {
84 ex.timer[i] += al_get_time();
85 }
86
get_fps(int i)87 static double get_fps(int i)
88 {
89 if (ex.timer[i] == 0)
90 return 0;
91 return ex.counter[i] / ex.timer[i];
92 }
93
draw(void)94 static void draw(void)
95 {
96 float x, y;
97 int iw = al_get_bitmap_width(ex.pattern);
98 int ih = al_get_bitmap_height(ex.pattern);
99 ALLEGRO_BITMAP *screen, *temp;
100 ALLEGRO_LOCKED_REGION *lock;
101 void *data;
102 int size, i, format;
103
104 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
105
106 al_clear_to_color(ex.background);
107
108 screen = al_get_target_bitmap();
109
110 set_xy(8, 8);
111
112 /* Test 1. */
113 /* Disabled: drawing to same bitmap is not supported. */
114 /*
115 print("Screen -> Screen (%.1f fps)", get_fps(0));
116 get_xy(&x, &y);
117 al_draw_bitmap(ex.pattern, x, y, 0);
118
119 start_timer(0);
120 al_draw_bitmap_region(screen, x, y, iw, ih, x + 8 + iw, y, 0);
121 stop_timer(0);
122 set_xy(x, y + ih);
123 */
124
125 /* Test 2. */
126 print("Screen -> Bitmap -> Screen (%.1f fps)", get_fps(1));
127 get_xy(&x, &y);
128 al_draw_bitmap(ex.pattern, x, y, 0);
129
130 temp = al_create_bitmap(iw, ih);
131 al_set_target_bitmap(temp);
132 al_clear_to_color(al_map_rgba_f(1, 0, 0, 1));
133 start_timer(1);
134 al_draw_bitmap_region(screen, x, y, iw, ih, 0, 0, 0);
135
136 al_set_target_bitmap(screen);
137 al_draw_bitmap(temp, x + 8 + iw, y, 0);
138 stop_timer(1);
139 set_xy(x, y + ih);
140
141 al_destroy_bitmap(temp);
142
143 /* Test 3. */
144 print("Screen -> Memory -> Screen (%.1f fps)", get_fps(2));
145 get_xy(&x, &y);
146 al_draw_bitmap(ex.pattern, x, y, 0);
147
148 al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP);
149 temp = al_create_bitmap(iw, ih);
150 al_set_target_bitmap(temp);
151 al_clear_to_color(al_map_rgba_f(1, 0, 0, 1));
152 start_timer(2);
153 al_draw_bitmap_region(screen, x, y, iw, ih, 0, 0, 0);
154
155 al_set_target_bitmap(screen);
156 al_draw_bitmap(temp, x + 8 + iw, y, 0);
157 stop_timer(2);
158 set_xy(x, y + ih);
159
160 al_destroy_bitmap(temp);
161 al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP);
162
163 /* Test 4. */
164 print("Screen -> Locked -> Screen (%.1f fps)", get_fps(3));
165 get_xy(&x, &y);
166 al_draw_bitmap(ex.pattern, x, y, 0);
167
168 start_timer(3);
169 lock = al_lock_bitmap_region(screen, x, y, iw, ih,
170 ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READONLY);
171 format = lock->format;
172 size = lock->pixel_size;
173 data = malloc(size * iw * ih);
174 for (i = 0; i < ih; i++)
175 memcpy((char*)data + i * size * iw,
176 (char*)lock->data + i * lock->pitch, size * iw);
177 al_unlock_bitmap(screen);
178
179 lock = al_lock_bitmap_region(screen, x + 8 + iw, y, iw, ih, format,
180 ALLEGRO_LOCK_WRITEONLY);
181 for (i = 0; i < ih; i++)
182 memcpy((char*)lock->data + i * lock->pitch,
183 (char*)data + i * size * iw, size * iw);
184 al_unlock_bitmap(screen);
185 free(data);
186 stop_timer(3);
187 set_xy(x, y + ih);
188
189 }
190
tick(void)191 static void tick(void)
192 {
193 draw();
194 al_flip_display();
195 }
196
run(void)197 static void run(void)
198 {
199 ALLEGRO_EVENT event;
200 bool need_draw = true;
201
202 while (1) {
203 if (need_draw && al_is_event_queue_empty(ex.queue)) {
204 tick();
205 need_draw = false;
206 }
207
208 al_wait_for_event(ex.queue, &event);
209
210 switch (event.type) {
211 case ALLEGRO_EVENT_DISPLAY_CLOSE:
212 return;
213
214 case ALLEGRO_EVENT_KEY_DOWN:
215 if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE)
216 return;
217 break;
218
219 case ALLEGRO_EVENT_TIMER:
220 need_draw = true;
221 break;
222 }
223 }
224 }
225
init(void)226 static void init(void)
227 {
228 ex.FPS = 60;
229
230 ex.font = al_load_font("data/fixed_font.tga", 0, 0);
231 if (!ex.font) {
232 abort_example("data/fixed_font.tga not found\n");
233 }
234 ex.background = al_color_name("beige");
235 ex.text = al_color_name("black");
236 ex.white = al_color_name("white");
237 ex.pattern = example_bitmap(100, 100);
238 }
239
main(int argc,char ** argv)240 int main(int argc, char **argv)
241 {
242 ALLEGRO_DISPLAY *display;
243 ALLEGRO_TIMER *timer;
244
245 (void)argc;
246 (void)argv;
247
248 if (!al_init()) {
249 abort_example("Could not init Allegro.\n");
250 }
251
252 al_install_keyboard();
253 al_install_mouse();
254 al_init_image_addon();
255 al_init_font_addon();
256 init_platform_specific();
257
258 display = al_create_display(640, 480);
259 if (!display) {
260 abort_example("Error creating display\n");
261 }
262
263 init();
264
265 timer = al_create_timer(1.0 / ex.FPS);
266
267 ex.queue = al_create_event_queue();
268 al_register_event_source(ex.queue, al_get_keyboard_event_source());
269 al_register_event_source(ex.queue, al_get_mouse_event_source());
270 al_register_event_source(ex.queue, al_get_display_event_source(display));
271 al_register_event_source(ex.queue, al_get_timer_event_source(timer));
272
273 al_start_timer(timer);
274 run();
275
276 al_destroy_event_queue(ex.queue);
277
278 return 0;
279 }
280