Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » [A5] al_flip_display() lag?

This thread is locked; no one can reply to it. rss feed Print
[A5] al_flip_display() lag?
Neil Roy
Member #2,229
April 2002
avatar

I have a problem with lag. I draw a title screen on an 800x600 screen, window or full screen can be selected via config file.

In Windowed mode, no problems at all.

When I switch to full screen (ALLEGRO_FULLSCREEN) there is a small lag before the screen is displayed.

I basically have simple code which draws a bitmap (800x600 jpg) and some ttf text, then flips the display and plays a sound sample...

al_flip_display();

al_play_sample...

...the sound sample plays about 1/4 of the way through before the display is actually shown.

Like I said, this works perfectly in Windowed mode with no lag at all.

Is there something perhaps I could check to make sure the display is flipped first? This concerns me though for other parts of the game later on, running in fullscreen mode, will there be a lag after flips, of just the first one. I'm not sure what the problem could be, it's a pretty basic setup. I'm not doing anything fancy or even loading a lot.

jmasterx
Member #11,410
October 2009

It's probably because Allegro has to go through the trouble of destroying and creating a new OS window when going fullscreen (I think so anyways, the source code shows that).

Maybe ALLEGRO_FULLSCREEN_WINDOW would give better results. There might also maybe be a switched in or expose event or something that you receive when doing that.

Matthew Leverton
Supreme Loser
January 1999
avatar

Sounds like it all happens via a config file, so I doubt he is destroying an existing display. The only thing that comes to mind is vsync, but I don't think you'd get that behavior.

Of course, make sure that you create the bitmap after creating the display, but that would affect windowed mode as well. You may want to supply minimal code that illustrates the problem.

Neil Roy
Member #2,229
April 2002
avatar

Yeah, I run the program, initialize everything. I am very careful about the order I do things in. No bitmaps are set until long after the display is set up. I set VSYNC & FULLSCREEN from a config file (I got that from one of the examples on vsync I think it was). Once the display is set early in the program it isn't changed again. I tested it with vsync set at 0 (system driver), 1 (forced on) and 2 (forced off) and the problem is still there. But only in Fullscreen mode. I don't do anything fancy with other settings (like blenders and such) as I want to be sure the program is running smoothly with normal default settings first.

It's puzzling because I wouldn't think I would be able to hear my sound sample at all until the flip was done, but it plays halfway through before the screen appears.

I have 10gigs of system memory and an nVidia GT240 video card, so I am not lacking in memory. CPU is quad core 3Ghz too.

Like I said, window mode and fullscreen window works. I like fullscreen window, but then I would have to hack away at some code to make everything display properly when I should be able to simply call a normal fullscreen mode and let the users monitor handle how to do that.

If I have to I will, but it seems like odd behavior and would be nice to find out why it is doing that.

Below is my initialization function, I cut out most of it and just commented what is there, but all code I do have was tested and works fine, I always check return values no matter how remote the chance of failing as I like to be safe...

#SelectExpand
1void initialize() 2{ 3 ALLEGRO_CONFIG *config; 4 5 al_init(); 6 // init everything else here... 7 8 // load config file and set variables, same code as in ex_vsync... 9 10 // initialize PHYSFS... 11 12 // display.vsync set to 2 in config file currently (this is taken from ex_vsync) 13 if (display.vsync) 14 al_set_new_display_option(ALLEGRO_VSYNC, display.vsync, ALLEGRO_SUGGEST); 15 16 // Force fullscreen mode. 17 if (display.fullscreen) { // enabled in config 18 al_set_new_display_flags(ALLEGRO_FULLSCREEN); 19 // Set a monitor frequency. 20 if (display.frequency) // from ex_vsync, set to 0 in config 21 al_set_new_display_refresh_rate(display.frequency); 22 } 23 24 // WIDTH = 800, HEIGHT = 600 25 display.screen = al_create_display(WIDTH, HEIGHT); 26 if(!display.screen) { 27 a5_error(AT, display.screen, "Create display failed."); 28 shut_down(); 29 exit(1); 30 } 31 display.w = al_get_display_width(display.screen); 32 display.h = al_get_display_height(display.screen); 33 34 // load and set icon + window title here 35 36 // load 4 TTF fonts here 37 38 // Create a timer for updating player movement 39 // created and enabled here (60), for testing 40 41 // Create a timer for updating enemy movement 42 // created and enabled here (120), for testing 43 44 // Create a timer for updating the screen 45 // Note: I created the other timers in a similar fashion 46 // only with their own variables 47 display.redraw_timer = al_create_timer(1.0 / 60); 48 if(display.redraw_timer == NULL) { 49 a5_error(AT, display.screen, "Failed to create redraw timer."); 50 shut_down(); 51 exit(1); 52 } 53 54 // Create event_queue here 55 56 // register all event sources here 57 58 // 3 timers started here 59 60 // Load a small 50x50 enemy bitmap here (for testing) 61 62 // Load a small 50x50 player bitmap here (for testing) 63 64 // install audio here 65 66 // reserve samples here 67}

My intro where the problem occurs.

#SelectExpand
1void intro() 2{ 3 int dw = display.w / 2; 4 int dh = display.h / 2; 5 6 ALLEGRO_SAMPLE *swamp = al_load_sample("snd/Swamp.wav"); 7 if (!swamp) { 8 a5_error(AT, display.screen, "Failed to load Swamp.wav"); 9 shut_down(); 10 exit(1); 11 } 12 13 ALLEGRO_BITMAP *background = al_load_bitmap("gfx/Latenight.jpg"); 14 if (!background) { 15 a5_error(AT, display.screen, "Failed to load Latenight.jpg"); 16 shut_down(); 17 exit(1); 18 } 19 20 al_draw_bitmap(background, display.offset, 0, 0); 21 22 al_draw_text(font_Amaze, al_map_rgb_f(.5,0,1), dw, dh-200, ALLEGRO_ALIGN_CENTRE, "Intro Text"); 23 al_draw_text(font_Bimini, al_map_rgb_f(.5,0,1), dw, dh+50, ALLEGRO_ALIGN_CENTRE, "Goes Here"); 24 25 al_flip_display(); 26 27 al_play_sample(swamp, 1.0, 0.0, 1.0, ALLEGRO_PLAYMODE_ONCE, NULL); 28 29 wait_for_keypress();

The end of the code above is where you get the delay before the screen appears, the sound plays for about 2 or
3 seconds before the screen appears, but only in ALLEGRO_FULLSCREEN mode.

And my main function...

int main(int argc, char *argv[])
{
   // set variables etc for use later here, non of  these effect the intro...

   initialize();

   intro();

No need to show more, this is where it branches off to do the intro mentioned above.

Edit: not that it matters, but all graphic, font and sound files are loaded from a ZIP file and shut_down() you see simply destroys anything that needs destroying before the game exits.

Matthew Leverton
Supreme Loser
January 1999
avatar

Neil Roy said:

I like fullscreen window, but then I would have to hack away at some code to make everything display properly when I should be able to simply call a normal fullscreen mode and let the users monitor handle how to do that.

It's possible that you'd only have to set a transformation on the display to automatically scale up when using a fullscreen window.

Anyway, does the same behavior exist if you use the OpenGL driver instead of the default D3D one?

Neil Roy
Member #2,229
April 2002
avatar

I just tried it with al_set_new_display_flags(ALLEGRO_FULLSCREEN|ALLEGRO_OPENGL); and there was less of a lag. It was almost right away, but not quite, still a small one, but much shorter lag.

I also tried it with lower resolution graphics (bitmaps are half the size) and lower quality sound (I changed the sound from a WAV to an OGG). They're MUCH smaller files to load etc... but there's no difference in lag.

I have an allegro log file, wish I knew what I was looking at. ;)

Edit: I attached the log file from the default Direct3D run.

Trent Gamblin
Member #261
April 2000
avatar

What version of Allegro 5 are you using? I think the latest release has a bug in d3d where the reference driver gets used as a fallback, which is extremely slow. It is fixed in svn.

Neil Roy
Member #2,229
April 2002
avatar

5.0.7

Edit:

It's possible that you'd only have to set a transformation on the display to automatically scale up when using a fullscreen window.

Also, I am not sure how to do this. I may fiddle around with ALLEGRO_FULLSCREEN_WINDOW and see if I can work something out with it, or just stick to opengl for now, at least until the next stable release comes out. I don't compile my own allegro anymore, all the dependencies seem to always give me problems. No big deal I guess, I'll be working on this project for a while anyhow.

Trent Gamblin
Member #261
April 2000
avatar

Yeah, I'm pretty sure that has the bug. If it does, it could be the cause. I didn't see your log there at first. I can't tell from the log if that's the problem. :-/

Neil Roy
Member #2,229
April 2002
avatar

I attached a log where I set the breakpoint in debug mode to immediately after al_flip_display();. I actually had to logoff my machine, couldn't break out of the program or even for it to shut down, sheesh Microsoft need to fix Task Manager! :-/

Matthew Leverton
Supreme Loser
January 1999
avatar

Here's what I was talking about regarding the transformations:

#SelectExpand
1 2#include <allegro5/allegro.h> 3#include <allegro5/allegro_image.h> 4#include <allegro5/allegro_primitives.h> 5 6void scale_screen(int bw, int bh, int dw, int dh) 7{ 8 ALLEGRO_TRANSFORM t; 9 10 // Calculate the horizontal and vertial aspect ratios 11 const float HAR = dw/(float)bw; 12 const float VAR = dh/(float)bh; 13 14 // The aspect ratio, x-offset and y-offset (in pixels) 15 float ar, ox, oy; 16 17 18 if (bw == dw && bh == dh) 19 { 20 // 1:1, just reset everything 21 al_identity_transform(&t); 22 al_use_transform(&t); 23 al_set_clipping_rectangle(0, 0, bw, bh); 24 } 25 else 26 { 27 // Choose the smaller aspect ratio 28 if (HAR < VAR) 29 { 30 // horizontal bars on the top and bottom 31 ar = HAR; 32 ox = 0; 33 oy = (dh - (ar * bh)) / 2.0; 34 } 35 else 36 { 37 // vertical bars on the left and right 38 ar = VAR; 39 ox = (dw - (ar * bw)) / 2.0; 40 oy = 0; 41 } 42 43 // set up the transformation to scale and translate 44 al_build_transform(&t, ox, oy, ar, ar, 0); 45 al_use_transform(&t); 46 47 // make sure nothing is drawn into the black bars 48 al_set_clipping_rectangle(ox, oy, ar * bw, ar * bh); 49 } 50} 51 52int main() 53{ 54 const int BUFFER_WIDTH = 400, BUFFER_HEIGHT = 400; 55 bool fullscreen = true; 56 57 ALLEGRO_BITMAP *bmp; 58 ALLEGRO_DISPLAY *display; 59 ALLEGRO_EVENT event; 60 ALLEGRO_EVENT_QUEUE *queue; 61 62 al_init(); 63 al_init_primitives_addon(); 64 al_init_image_addon(); 65 al_install_keyboard(); 66 67 queue = al_create_event_queue(); 68 al_register_event_source(queue, al_get_keyboard_event_source()); 69 70 al_set_new_display_flags(ALLEGRO_FULLSCREEN_WINDOW); 71 display = al_create_display(BUFFER_WIDTH, BUFFER_HEIGHT); 72 73 bmp = al_load_bitmap("test.png"); 74 75 scale_screen(BUFFER_WIDTH, BUFFER_HEIGHT, al_get_display_width(display), al_get_display_height(display)); 76 77 while (true) 78 { 79 al_draw_filled_rectangle(0, 0, BUFFER_WIDTH, BUFFER_HEIGHT, al_map_rgb(255,255,255)); 80 al_draw_rectangle(0.5, 0.5, BUFFER_WIDTH - 0.5, BUFFER_HEIGHT - 0.5, al_map_rgb(255,0,0), 1.0); 81 if (bmp) 82 al_draw_bitmap(bmp, 0, 0, 0); 83 al_flip_display(); 84 85 al_wait_for_event(queue, &event); 86 87 if (event.type == ALLEGRO_EVENT_KEY_UP) 88 { 89 if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE) 90 { 91 // quit 92 break; 93 } 94 else if (event.keyboard.keycode == ALLEGRO_KEY_SPACE) 95 { 96 // toggle fullscreen mode 97 fullscreen = !fullscreen; 98 al_set_display_flag(display, ALLEGRO_FULLSCREEN_WINDOW, fullscreen); 99 scale_screen(BUFFER_WIDTH, BUFFER_HEIGHT, al_get_display_width(display), al_get_display_height(display)); 100 } 101 } 102 } 103 return 0; 104}

For this demo, you should see a white box with a red outline and test.png (if exists) drawn at (0,0). Press space to toggle windowed mode; escape to exit.

Adjust BUFFER_WIDTH and BUFFER_HEIGHT to whatever you like. (It represents the native resolution of the game.)

If you look at the drawing in the main loop, you'll see it just draws using the native resolution, regardless of what the display's resolution is. The call to scale_screen() sets everything up so that it gets drawn stretched to the max with black bars in full screen mode.

Neil Roy
Member #2,229
April 2002
avatar

I check the docs and started looking at anything I could find on transformations. Looked at ex_transform, started to play around with it.

It took me a while of fiddling around with the number to figure it out, but I managed to come up with this (before reading your post). ;)

   display.w = al_get_display_width(display.screen);
   display.h = al_get_display_height(display.screen);

   display.scale = (float)display.h / (float)HEIGHT;
   display.move = (float)(display.w - (WIDTH*display.scale))/2;
   al_identity_transform(&transform);
   al_scale_transform(&transform, display.scale, display.scale);
   al_translate_transform(&transform, display.move, 0);
   al_use_transform(&transform);

I placed that after I create the display and it works great!

For certain screens I added:

   al_draw_filled_rectangle(-display.move, 0, -1, HEIGHT, al_map_rgb_f(0,0,0));
   al_draw_filled_rectangle(WIDTH, 0, WIDTH+display.move, HEIGHT,
                            al_map_rgb_f(0,0,0));

That puts a black box on each side.

I'm not sure if there is a better way, but this works, I am quite pleased, I didn't think I would be able to grasp how to do a transform.

I can plug this into any other program as it is quite portable, just set WIDTH and HEIGHT to the resolution you want. I think I should probably put some sort of checks in there but it's too late for me to think, my brain is already about to explode. :D

EDIT: Hmmm, I may use the code you posted instead, look prettier. :D

Matthew Leverton
Supreme Loser
January 1999
avatar

Your code is fine, but it only works if bars are on the left/right. That's the more usual case, but if you have a widescreen game and want to draw it on a 4:3 monitor, you'll need bars across the top and bottom.

The clipping rectangle is important because otherwise something may overlap into the black bar area that normally would be automatically clipped by the size of the monitor.

Some options that may be useful:

// sampling for primitives
al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 1, ALLEGRO_SUGGEST);
al_set_new_display_option(ALLEGRO_SAMPLES, 4, ALLEGRO_SUGGEST);

// linear filter when scaling bitmaps up
al_set_new_bitmap_flags(ALLEGRO_MAG_LINEAR | ALLEGRO_VIDEO_BITMAP);

The bitmap flag could be enable/disabled on a per bitmap basis.

weapon_S
Member #7,859
October 2006
avatar

where the reference driver gets used as a fallback, which is extremely slow.

OMG that might explain why it suddenly turned dirty fast on my ancient hardware ><

Neil Roy
Member #2,229
April 2002
avatar

Your code is fine, but it only works if bars are on the left/right. That's the more usual case, but if you have a widescreen game and want to draw it on a 4:3 monitor, you'll need bars across the top and bottom.

Yeah, I noticed that about your code, part of why I liked yours better. I never thought of that and even though this game isn't widescreen, I would like to have that option for future games.

Quote:

The clipping rectangle is important because otherwise something may overlap into the black bar area that normally would be automatically clipped by the size of the monitor.

Yeah, good point. I seen your clipping rectangle code, I didn't know about that function. This is my first large A5 project. Another good reason to use your code. ;)

Still, I am proud of the fact that I managed to figure out some solution on my own first. I was up until 2am working on this, brings back memories of when I used to program in the '90s with Allegro 2 until the wee hours of the morning. Been a while. I'm really liking Allegro 5 now though, took me a while to unlearn some A4 stuff. ;)

Thanks a lot for all your help. It's much appreciated.

Matthew Leverton
Supreme Loser
January 1999
avatar

Neil Roy said:

Still, I am proud of the fact that I managed to figure out some solution on my own first

That's the best way to learn. Unfortunately, it seems like programmers have gone from figuring things out from documentation to searching Google to just asking somebody for the code. :'(

Neil Roy
Member #2,229
April 2002
avatar

I was just talking with my wife (probably boring her to death, ;D) about programming, part of the fun is in figuring out how to do it on your own first, at least for me. I don't think I have enjoyed myself so much as I did last night working on t his project. I'm rewriting my Deluxe Pacman game from scratch, creating a version 2. I have quite a few people around the world that like it, so I want to remake it using Allegro 5, adding in Low resolution and High resolution sounds and graphics as well so low end systems can run it. It's been fun. I actually was floored the other day when I got a donation for my old game for $100. Making a total donations for it at $175... lets see, after 13 years of work, that means I work for 13 bucks a year! LMAO :D Well, it's better than the 5 it used to be. ;)

I took your function and made a header for it. I'll use it in future games. I have attached it in case anyone else wants to plug it into theirs. Did you program that function? I wanted to give proper credit in it but wasn't sure who to credit.

Anyhow, zip contains the .c and .h header. It would make a good example program (if it isn't already) and even tutorial.

Arthur Kalliokoski
Second in Command
February 2005
avatar

it seems like programmers have gone from figuring things out from documentation to searching Google to just asking somebody for the code.

I've been sucking on the Google tit myself, it's easier to search Google than to CTRL-F some pdf and if I'm lucky, get one specific example that invariably differs from my problem. But usually my problem is so specific that a programming forum doesn't know the answer off the top of their head, so they have to Google or whatever themselves if they want to help.

“Throughout history, poverty is the normal condition of man. Advances which permit this norm to be exceeded — here and there, now and then — are the work of an extremely small minority, frequently despised, often condemned, and almost always opposed by all right-thinking people. Whenever this tiny minority is kept from creating, or (as sometimes happens) is driven out of a society, the people then slip back into abject poverty. This is known as "bad luck.”

― Robert A. Heinlein

Neil Roy
Member #2,229
April 2002
avatar

I've been using Google, but just to search the allegro manual, it's the first thing to come up when I enter an A5 function name, so it's just faster. ;)

Matthew Leverton
Supreme Loser
January 1999
avatar

Neil Roy said:

Did you program that function? I wanted to give proper credit in it but wasn't sure who to credit.

I did, but there's no need to give credit. There's pretty much only one reasonable way to do it.

Go to: