/* An example comparing different ways of drawing polygons, including usage of * vertex buffers. */ #include #include #include #include #include "common.c" #define FPS 60 #define FRAME_TAU 60 #define NUM_VERTICES 4096 typedef struct METHOD METHOD; struct METHOD { float x; float y; ALLEGRO_VERTEX_BUFFER *vbuff; ALLEGRO_VERTEX *vertices; const char *name; int flags; double frame_average; }; static ALLEGRO_COLOR get_color(size_t ii) { double t = al_get_time(); double frac = (float)(ii) / NUM_VERTICES; #define THETA(period) ((t / (period) + frac) * 2 * ALLEGRO_PI) return al_map_rgb_f(sin(THETA(5.0)) / 2 + 1, cos(THETA(1.1)) / 2 + 1, sin(THETA(3.4) / 2) / 2 + 1); } static void draw_method(METHOD *md, ALLEGRO_FONT *font, ALLEGRO_VERTEX* new_vertices) { ALLEGRO_TRANSFORM t; double start_time; double new_fps; ALLEGRO_COLOR c; al_identity_transform(&t); al_translate_transform(&t, md->x, md->y); al_use_transform(&t); al_draw_textf(font, al_map_rgb_f(1, 1, 1), 0, -50, ALLEGRO_ALIGN_CENTRE, "%s%s", md->name, md->flags & ALLEGRO_PRIM_BUFFER_READWRITE ? "+read/write" : "+write-only"); start_time = al_get_time(); if (md->vbuff) { if (new_vertices) { void* lock_mem = al_lock_vertex_buffer(md->vbuff, 0, NUM_VERTICES, ALLEGRO_LOCK_WRITEONLY); memcpy(lock_mem, new_vertices, sizeof(ALLEGRO_VERTEX) * NUM_VERTICES); al_unlock_vertex_buffer(md->vbuff); } al_draw_vertex_buffer(md->vbuff, 0, 0, NUM_VERTICES, ALLEGRO_PRIM_TRIANGLE_STRIP); } else if (md->vertices) { al_draw_prim(md->vertices, 0, 0, 0, NUM_VERTICES, ALLEGRO_PRIM_TRIANGLE_STRIP); } /* Force the completion of the previous commands by reading from screen */ c = al_get_pixel(al_get_backbuffer(al_get_current_display()), 0, 0); (void)c; new_fps = 1.0 / (al_get_time() - start_time); md->frame_average += (new_fps - md->frame_average) / FRAME_TAU; if (md->vbuff || md->vertices) { al_draw_textf(font, al_map_rgb_f(1, 0, 0), 0, 0, ALLEGRO_ALIGN_CENTRE, "%.1e FPS", md->frame_average); } else { al_draw_text(font, al_map_rgb_f(1, 0, 0), 0, 0, ALLEGRO_ALIGN_CENTRE, "N/A"); } al_identity_transform(&t); al_use_transform(&t); } int main(int argc, char **argv) { ALLEGRO_TIMER *timer; ALLEGRO_EVENT_QUEUE *queue; ALLEGRO_DISPLAY *display; ALLEGRO_FONT *font; int w = 640, h = 480; bool done = false; bool need_redraw = true; bool background = false; bool dynamic_buffers = false; size_t num_methods; int num_x = 3; int num_y = 3; int spacing_x = 200; int spacing_y = 150; size_t ii; ALLEGRO_VERTEX* vertices; (void)argc; (void)argv; if (!al_init()) { abort_example("Failed to init Allegro.\n"); } al_init_font_addon(); al_init_primitives_addon(); #ifdef ALLEGRO_IPHONE al_set_new_display_flags(ALLEGRO_FULLSCREEN_WINDOW); #endif al_set_new_display_option(ALLEGRO_SUPPORTED_ORIENTATIONS, ALLEGRO_DISPLAY_ORIENTATION_ALL, ALLEGRO_SUGGEST); display = al_create_display(w, h); if (!display) { abort_example("Error creating display.\n"); } w = al_get_display_width(display); h = al_get_display_height(display); al_install_keyboard(); font = al_create_builtin_font(); timer = al_create_timer(1.0 / FPS); queue = al_create_event_queue(); al_register_event_source(queue, al_get_keyboard_event_source()); al_register_event_source(queue, al_get_timer_event_source(timer)); al_register_event_source(queue, al_get_display_event_source(display)); vertices = al_malloc(sizeof(ALLEGRO_VERTEX) * NUM_VERTICES); al_calculate_arc(&vertices[0].x, sizeof(ALLEGRO_VERTEX), 0, 0, 80, 30, 0, 2 * ALLEGRO_PI, 10, NUM_VERTICES / 2); for (ii = 0; ii < NUM_VERTICES; ii++) { vertices[ii].z = 0; vertices[ii].color = get_color(ii); } { #define GETX(n) ((w - (num_x - 1) * spacing_x) / 2 + n * spacing_x) #define GETY(n) ((h - (num_y - 1) * spacing_y) / 2 + n * spacing_y) METHOD methods[] = { {GETX(1), GETY(0), 0, vertices, "No buffer", 0, 0}, {GETX(0), GETY(1), 0, 0, "STREAM", ALLEGRO_PRIM_BUFFER_STREAM | ALLEGRO_PRIM_BUFFER_READWRITE, 0}, {GETX(1), GETY(1), 0, 0, "STATIC", ALLEGRO_PRIM_BUFFER_STATIC | ALLEGRO_PRIM_BUFFER_READWRITE, 0}, {GETX(2), GETY(1), 0, 0, "DYNAMIC", ALLEGRO_PRIM_BUFFER_STREAM | ALLEGRO_PRIM_BUFFER_READWRITE, 0}, {GETX(0), GETY(2), 0, 0, "STREAM", ALLEGRO_PRIM_BUFFER_STREAM, 0}, {GETX(1), GETY(2), 0, 0, "STATIC", ALLEGRO_PRIM_BUFFER_STATIC, 0}, {GETX(2), GETY(2), 0, 0, "DYNAMIC", ALLEGRO_PRIM_BUFFER_DYNAMIC, 0} }; num_methods = sizeof(methods) / sizeof(METHOD); for (ii = 0; ii < num_methods; ii++) { METHOD* md = &methods[ii]; md->frame_average = 1; if (!md->vertices) md->vbuff = al_create_vertex_buffer(0, vertices, NUM_VERTICES, md->flags); } al_start_timer(timer); while (!done) { ALLEGRO_EVENT event; if (!background && need_redraw && al_is_event_queue_empty(queue)) { al_clear_to_color(al_map_rgb_f(0, 0, 0.2)); for (ii = 0; ii < num_methods; ii++) draw_method(&methods[ii], font, dynamic_buffers ? vertices : 0); al_draw_textf(font, al_map_rgb_f(1, 1, 1), 10, 10, 0, "Dynamic (D): %s", dynamic_buffers ? "yes" : "no"); al_flip_display(); need_redraw = false; } al_wait_for_event(queue, &event); switch (event.type) { case ALLEGRO_EVENT_KEY_DOWN: if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE) done = true; else if(event.keyboard.keycode == ALLEGRO_KEY_D) dynamic_buffers = !dynamic_buffers; break; case ALLEGRO_EVENT_DISPLAY_CLOSE: done = true; break; case ALLEGRO_EVENT_DISPLAY_HALT_DRAWING: background = true; al_acknowledge_drawing_halt(event.display.source); break; case ALLEGRO_EVENT_DISPLAY_RESIZE: al_acknowledge_resize(event.display.source); break; case ALLEGRO_EVENT_DISPLAY_RESUME_DRAWING: background = false; break; case ALLEGRO_EVENT_TIMER: for (ii = 0; ii < NUM_VERTICES; ii++) vertices[ii].color = get_color(ii); need_redraw = true; break; } } for (ii = 0; ii < num_methods; ii++) al_destroy_vertex_buffer(methods[ii].vbuff); al_destroy_font(font); al_free(vertices); } return 0; }