![]() |
|
[A5] al_flip_display() lag? |
Neil Roy
Member #2,229
April 2002
![]() |
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. Agui GUI API -> https://github.com/jmasterx/Agui |
Matthew Leverton
Supreme Loser
January 1999
![]() |
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
![]() |
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... 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. 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 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
![]() |
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
![]() |
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
![]() |
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
![]() |
5.0.7 Edit: Matthew Leverton said: 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
![]() |
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
![]() |
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
![]() |
Here's what I was talking about regarding the transformations: 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
![]() |
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. EDIT: Hmmm, I may use the code you posted instead, look prettier. --- |
Matthew Leverton
Supreme Loser
January 1999
![]() |
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
![]() |
Trent Gamblin said: 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
![]() |
Matthew Leverton said: 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
![]() |
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
![]() |
I was just talking with my wife (probably boring her to death, 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
![]() |
Matthew Leverton said: 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. They all watch too much MSNBC... they get ideas. |
Neil Roy
Member #2,229
April 2002
![]() |
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
![]() |
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. |
|