/* An example demonstrating different blending modes. */ #include #include #include #include #include #include #include #include "common.c" struct Example { ALLEGRO_BITMAP *pattern; ALLEGRO_FONT *font; ALLEGRO_EVENT_QUEUE *queue; ALLEGRO_COLOR background, text, white; double timer[4], counter[4]; int FPS; float text_x, text_y; } ex; static ALLEGRO_BITMAP *example_bitmap(int w, int h) { int i, j; float mx = w * 0.5; float my = h * 0.5; ALLEGRO_STATE state; ALLEGRO_BITMAP *pattern = al_create_bitmap(w, h); al_store_state(&state, ALLEGRO_STATE_TARGET_BITMAP); al_set_target_bitmap(pattern); al_lock_bitmap(pattern, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_WRITEONLY); for (i = 0; i < w; i++) { for (j = 0; j < h; j++) { float a = atan2(i - mx, j - my); float d = sqrt(pow(i - mx, 2) + pow(j - my, 2)); float sat = pow(1.0 - 1 / (1 + d * 0.1), 5); float hue = 3 * a * 180 / ALLEGRO_PI; hue = (hue / 360 - floorf(hue / 360)) * 360; al_put_pixel(i, j, al_color_hsv(hue, sat, 1)); } } al_put_pixel(0, 0, al_map_rgb(0, 0, 0)); al_unlock_bitmap(pattern); al_restore_state(&state); return pattern; } static void set_xy(float x, float y) { ex.text_x = x; ex.text_y = y; } static void get_xy(float *x, float *y) { *x = ex.text_x; *y = ex.text_y; } static void print(char const *format, ...) { va_list list; char message[1024]; int th = al_get_font_line_height(ex.font); va_start(list, format); vsnprintf(message, sizeof message, format, list); va_end(list); al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA); al_draw_textf(ex.font, ex.text, ex.text_x, ex.text_y, 0, "%s", message); ex.text_y += th; } static void start_timer(int i) { ex.timer[i] -= al_get_time(); ex.counter[i]++; } static void stop_timer(int i) { ex.timer[i] += al_get_time(); } static double get_fps(int i) { if (ex.timer[i] == 0) return 0; return ex.counter[i] / ex.timer[i]; } static void draw(void) { float x, y; int iw = al_get_bitmap_width(ex.pattern); int ih = al_get_bitmap_height(ex.pattern); ALLEGRO_BITMAP *screen, *temp; ALLEGRO_LOCKED_REGION *lock; void *data; int size, i, format; al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO); al_clear_to_color(ex.background); screen = al_get_target_bitmap(); set_xy(8, 8); /* Test 1. */ /* Disabled: drawing to same bitmap is not supported. */ /* print("Screen -> Screen (%.1f fps)", get_fps(0)); get_xy(&x, &y); al_draw_bitmap(ex.pattern, x, y, 0); start_timer(0); al_draw_bitmap_region(screen, x, y, iw, ih, x + 8 + iw, y, 0); stop_timer(0); set_xy(x, y + ih); */ /* Test 2. */ print("Screen -> Bitmap -> Screen (%.1f fps)", get_fps(1)); get_xy(&x, &y); al_draw_bitmap(ex.pattern, x, y, 0); temp = al_create_bitmap(iw, ih); al_set_target_bitmap(temp); al_clear_to_color(al_map_rgba_f(1, 0, 0, 1)); start_timer(1); al_draw_bitmap_region(screen, x, y, iw, ih, 0, 0, 0); al_set_target_bitmap(screen); al_draw_bitmap(temp, x + 8 + iw, y, 0); stop_timer(1); set_xy(x, y + ih); al_destroy_bitmap(temp); /* Test 3. */ print("Screen -> Memory -> Screen (%.1f fps)", get_fps(2)); get_xy(&x, &y); al_draw_bitmap(ex.pattern, x, y, 0); al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP); temp = al_create_bitmap(iw, ih); al_set_target_bitmap(temp); al_clear_to_color(al_map_rgba_f(1, 0, 0, 1)); start_timer(2); al_draw_bitmap_region(screen, x, y, iw, ih, 0, 0, 0); al_set_target_bitmap(screen); al_draw_bitmap(temp, x + 8 + iw, y, 0); stop_timer(2); set_xy(x, y + ih); al_destroy_bitmap(temp); al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP); /* Test 4. */ print("Screen -> Locked -> Screen (%.1f fps)", get_fps(3)); get_xy(&x, &y); al_draw_bitmap(ex.pattern, x, y, 0); start_timer(3); lock = al_lock_bitmap_region(screen, x, y, iw, ih, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READONLY); format = lock->format; size = lock->pixel_size; data = malloc(size * iw * ih); for (i = 0; i < ih; i++) memcpy((char*)data + i * size * iw, (char*)lock->data + i * lock->pitch, size * iw); al_unlock_bitmap(screen); lock = al_lock_bitmap_region(screen, x + 8 + iw, y, iw, ih, format, ALLEGRO_LOCK_WRITEONLY); for (i = 0; i < ih; i++) memcpy((char*)lock->data + i * lock->pitch, (char*)data + i * size * iw, size * iw); al_unlock_bitmap(screen); free(data); stop_timer(3); set_xy(x, y + ih); } static void tick(void) { draw(); al_flip_display(); } static void run(void) { ALLEGRO_EVENT event; bool need_draw = true; while (1) { if (need_draw && al_is_event_queue_empty(ex.queue)) { tick(); need_draw = false; } al_wait_for_event(ex.queue, &event); switch (event.type) { case ALLEGRO_EVENT_DISPLAY_CLOSE: return; case ALLEGRO_EVENT_KEY_DOWN: if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE) return; break; case ALLEGRO_EVENT_TIMER: need_draw = true; break; } } } static void init(void) { ex.FPS = 60; ex.font = al_load_font("data/fixed_font.tga", 0, 0); if (!ex.font) { abort_example("data/fixed_font.tga not found\n"); } ex.background = al_color_name("beige"); ex.text = al_color_name("black"); ex.white = al_color_name("white"); ex.pattern = example_bitmap(100, 100); } int main(int argc, char **argv) { ALLEGRO_DISPLAY *display; ALLEGRO_TIMER *timer; (void)argc; (void)argv; if (!al_init()) { abort_example("Could not init Allegro.\n"); } al_install_keyboard(); al_install_mouse(); al_init_image_addon(); al_init_font_addon(); init_platform_specific(); display = al_create_display(640, 480); if (!display) { abort_example("Error creating display\n"); } init(); timer = al_create_timer(1.0 / ex.FPS); ex.queue = al_create_event_queue(); al_register_event_source(ex.queue, al_get_keyboard_event_source()); al_register_event_source(ex.queue, al_get_mouse_event_source()); al_register_event_source(ex.queue, al_get_display_event_source(display)); al_register_event_source(ex.queue, al_get_timer_event_source(timer)); al_start_timer(timer); run(); al_destroy_event_queue(ex.queue); return 0; }