*/
#include <allegro5/allegro.h>
#include <allegro5/allegro_font.h>
#include <allegro5/allegro_image.h>
#include <allegro5/allegro_color.h>
#include <stdio.h>
#include <stdarg.h>
#include <math.h>
#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);
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);
*/
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);
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);
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;
}