Show exupdate.c syntax highlighted
/*
* Example program for the Allegro library, by Shawn Hargreaves.
*
* This program demonstrates how to support double buffering, page
* flipping, and triple buffering as options within a single program,
* and how to make things run at a constant rate no matter what the
* speed of your computer.
*/
#include "allegro.h"
/* number of video memory pages:
* 1 = double buffered
* 2 = page flipping
* 3 = triple buffered
*/
int num_pages;
int use_system_bitmaps;
/* counters for speed control and frame rate measurement */
volatile int update_count = 0;
volatile int frame_count = 0;
volatile int fps = 0;
/* timer callback for controlling the program speed */
void timer_proc(void)
{
update_count++;
}
AL_END_OF_FUNCTION(timer_proc);
/* timer callback for measuring the framerate */
void fps_proc(void)
{
fps = frame_count;
frame_count = 0;
}
AL_END_OF_FUNCTION(fps_proc);
/* some rotation values for the graphical effect */
fixed r1 = 0;
fixed r2 = 0;
fixed r3 = 0;
fixed r4 = 0;
/* helper to draw four mirrored versions of a al_draw_triangle */
void kalid(AL_BITMAP *bmp, int x1, int y1, int x2, int y2, int x3, int y3, int r, int g, int b)
{
al_draw_triangle(bmp, AL_SCREEN_W/2+x1, AL_SCREEN_H/2+y1, AL_SCREEN_W/2+x2, AL_SCREEN_H/2+y2, AL_SCREEN_W/2+x3, AL_SCREEN_H/2+y3, al_make_color(r, g, b));
al_draw_triangle(bmp, AL_SCREEN_W/2-x1, AL_SCREEN_H/2+y1, AL_SCREEN_W/2-x2, AL_SCREEN_H/2+y2, AL_SCREEN_W/2-x3, AL_SCREEN_H/2+y3, al_make_color(r, g, b));
al_draw_triangle(bmp, AL_SCREEN_W/2-x1, AL_SCREEN_H/2-y1, AL_SCREEN_W/2-x2, AL_SCREEN_H/2-y2, AL_SCREEN_W/2-x3, AL_SCREEN_H/2-y3, al_make_color(r, g, b));
al_draw_triangle(bmp, AL_SCREEN_W/2+x1, AL_SCREEN_H/2-y1, AL_SCREEN_W/2+x2, AL_SCREEN_H/2-y2, AL_SCREEN_W/2+x3, AL_SCREEN_H/2-y3, al_make_color(r, g, b));
}
/* draws the current animation frame into the specified bitmap */
void draw_screen(AL_BITMAP *bmp)
{
fixed c1 = al_fix_cos(r1);
fixed c2 = al_fix_cos(r2);
fixed c3 = al_fix_cos(r3);
fixed c4 = al_fix_cos(r4);
fixed s1 = al_fix_sin(r1);
fixed s2 = al_fix_sin(r2);
fixed s3 = al_fix_sin(r3);
fixed s4 = al_fix_sin(r4);
al_acquire_bitmap(bmp);
al_clear_bitmap(bmp);
al_drawing_mode(DRAW_MODE_XOR, NULL, 0, 0);
kalid(bmp, al_fix_to_int(c1*AL_SCREEN_W/3), al_fix_to_int(s1*AL_SCREEN_H/3),
al_fix_to_int(c2*AL_SCREEN_W/3), al_fix_to_int(s2*AL_SCREEN_H/3),
al_fix_to_int(c3*AL_SCREEN_W/3), al_fix_to_int(s3*AL_SCREEN_H/3),
127+al_fix_to_int(c1*127), 127+al_fix_to_int(c2*127), 127+al_fix_to_int(c3*127));
kalid(bmp, al_fix_to_int(s1*AL_SCREEN_W/3), al_fix_to_int(c2*AL_SCREEN_H/3),
al_fix_to_int(s3*AL_SCREEN_W/3), al_fix_to_int(c4*AL_SCREEN_H/3),
al_fix_to_int(c3*AL_SCREEN_W/3), al_fix_to_int(s4*AL_SCREEN_H/3),
127+al_fix_to_int(s1*127), 127+al_fix_to_int(c4*127), 127+al_fix_to_int(s4*127));
kalid(bmp, al_fix_to_int(al_fix_mul(s2, c3)*AL_SCREEN_W/3), al_fix_to_int(c1*AL_SCREEN_H/3),
al_fix_to_int(c4*AL_SCREEN_W/3), al_fix_to_int(al_fix_mul(c2, s3)*AL_SCREEN_H/3),
al_fix_to_int(al_fix_mul(c3, s4)*AL_SCREEN_W/3), al_fix_to_int(s1*AL_SCREEN_H/3),
127+al_fix_to_int(s2*127), 127+al_fix_to_int(c3*127), 127+al_fix_to_int(s3*127));
al_drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
al_text_mode(-1);
if (num_pages == 1) {
if (use_system_bitmaps)
al_put_text(bmp, al_font_8x8, "Double buffered (system bitmap)", 0, 0, al_make_color(255, 255, 255));
else
al_put_text(bmp, al_font_8x8, "Double buffered (memory bitmap)", 0, 0, al_make_color(255, 255, 255));
}
else if (num_pages == 2)
al_put_text(bmp, al_font_8x8, "Page flipping (two pages of vram)", 0, 0, al_make_color(255, 255, 255));
else
al_put_text(bmp, al_font_8x8, "Triple buffered (three pages of vram)", 0, 0, al_make_color(255, 255, 255));
al_put_text(bmp, al_font_8x8, gfx_driver->name, 0, 16, al_make_color(255, 255, 255));
al_printf_text(bmp, al_font_8x8, 0, 32, al_make_color(255, 255, 255), "FPS: %d", fps);
al_release_bitmap(bmp);
}
/* called at a regular speed to update the program state */
void do_update(void)
{
r1 += al_float_to_fix(0.5);
r2 += al_float_to_fix(0.6);
r3 += al_float_to_fix(0.11);
r4 += al_float_to_fix(0.13);
}
int main(int argc, char *argv[])
{
AL_PALETTE pal;
AL_BITMAP *bmp[3];
int card = AL_GFX_AUTODETECT;
int w, h, bpp, page, i;
allegro_init();
/* check command al_draw_line arguments */
if (argc == 2)
num_pages = atoi(argv[1]);
else
num_pages = 0;
if (num_pages == 4) {
num_pages = 1;
use_system_bitmaps = TRUE;
}
else
use_system_bitmaps = FALSE;
if ((num_pages < 1) || (num_pages > 3)) {
al_show_message("\nUsage: 'exupdate num_pages', where num_pages is one of:\n\n"
"1 = double buffered (memory bitmap)\n\n"
" + easy, reliable\n"
" + drawing onto a memory bitmap is very fast\n"
" - blitting the finished image to the al_screen can be quite slow\n\n"
"2 = page flipping (two pages of video memory)\n\n"
" + avoids the need for a memory to al_screen al_blit of the completed image\n"
" + can use hardware acceleration when it is available\n"
" - drawing directly to vram can be slower than using a memory bitmap\n"
" - requires a card with enough video memory for two al_screen pages\n"
" - some VESA drivers have nasty bugs in the scrolling functions\n\n"
"3 = triple buffered (three pages of video memory)\n\n"
" + like page flipping, but faster and smoother\n"
" - requires a card with enough video memory for three al_screen pages\n"
" - only possible in mode-X (not win95), or with VBE 3.0 or VBE/AF\n\n"
"4 = double buffered (system bitmap)\n\n"
" + as easy as normal double buffering\n"
" + system bitmaps can be hardware accelerated on some platforms\n"
" - drawing to system bitmaps is sometimes slower than memory bitmaps\n\n");
return 1;
}
/* set up Allegro */
al_install_keyboard();
al_install_timer();
al_install_mouse();
if (al_set_gfx_mode(AL_GFX_SAFE, 320, 200, 0, 0) != 0) {
al_set_gfx_mode(AL_GFX_NONE, 0, 0, 0, 0);
al_show_message("Unable to set any graphic mode\n%s\n", al_error);
return 1;
}
al_set_palette(al_desktop_palette);
w = AL_SCREEN_W;
h = AL_SCREEN_H;
bpp = al_bitmap_color_depth(al_screen);
if (!al_select_gfx_mode(&card, &w, &h, &bpp))
return 0;
al_set_color_depth(bpp);
if (al_set_gfx_mode(card, w, h, 0, 0) != 0) {
al_set_gfx_mode(AL_GFX_NONE, 0, 0, 0, 0);
al_show_message("Error setting graphics mode\n%s\n", al_error);
return 1;
}
al_generate_332_palette(pal);
pal[0].r = pal[0].g = pal[0].b = 0;
al_set_palette(pal);
switch (num_pages) {
case 1:
/* double buffering setup */
if (use_system_bitmaps)
bmp[0] = al_create_system_bitmap(AL_SCREEN_W, AL_SCREEN_H);
else
bmp[0] = al_create_bitmap(AL_SCREEN_W, AL_SCREEN_H);
break;
case 2:
/* page flipping setup */
bmp[0] = al_create_video_bitmap(AL_SCREEN_W, AL_SCREEN_H);
bmp[1] = al_create_video_bitmap(AL_SCREEN_W, AL_SCREEN_H);
break;
case 3:
/* triple buffering setup */
if (!(al_gfx_capabilities & AL_GFX_CAN_TRIPLE_BUFFER))
al_enable_triple_buffer();
if (!(al_gfx_capabilities & AL_GFX_CAN_TRIPLE_BUFFER)) {
al_set_gfx_mode(AL_GFX_NONE, 0, 0, 0, 0);
#ifdef ALLEGRO_DOS
al_show_message("This driver does not support triple buffering\n\nTry using mode-X in clean DOS mode (not under Windows)\n");
#else
al_show_message("This driver does not support triple buffering\n");
#endif
return 1;
}
bmp[0] = al_create_video_bitmap(AL_SCREEN_W, AL_SCREEN_H);
bmp[1] = al_create_video_bitmap(AL_SCREEN_W, AL_SCREEN_H);
bmp[2] = al_create_video_bitmap(AL_SCREEN_W, AL_SCREEN_H);
break;
}
for (i=0; i<num_pages; i++) {
if (!bmp[i]) {
al_set_gfx_mode(AL_GFX_NONE, 0, 0, 0, 0);
al_show_message("Unable to create %d video memory pages\n", num_pages);
return 1;
}
}
/* install timer handlers to control and measure the program speed */
LOCK_VARIABLE(update_count);
LOCK_VARIABLE(frame_count);
LOCK_VARIABLE(fps);
LOCK_FUNCTION(timer_proc);
LOCK_FUNCTION(fps_proc);
al_create_timer(timer_proc, BPS_TO_TIMER(60));
al_create_timer(fps_proc, BPS_TO_TIMER(1));
page = 1;
/* main program loop */
while (!al_key_pressed()) {
/* draw the next frame of graphics */
switch (num_pages) {
case 1:
/* draw onto a memory bitmap, then al_blit to the al_screen */
draw_screen(bmp[0]);
al_vsync();
al_blit(bmp[0], al_screen, 0, 0, 0, 0, AL_SCREEN_W, AL_SCREEN_H);
break;
case 2:
/* flip back and forth between two pages of video memory */
draw_screen(bmp[page]);
al_show_video_bitmap(bmp[page]);
page = 1-page;
break;
case 3:
/* triple buffering */
draw_screen(bmp[page]);
do {
} while (al_poll_scroll());
al_request_video_bitmap(bmp[page]);
page = (page+1)%3;
break;
}
/* update the program state */
while (update_count > 0) {
do_update();
update_count--;
}
frame_count++;
}
for (i=0; i<num_pages; i++)
al_destroy_bitmap(bmp[i]);
return 0;
}
AL_END_OF_MAIN();
See more files for this project here