- You know that 1000/60 = 16.67, and 16x60 = 960 miliseconds. In other words, Allegro doesn't keep my program running at exactly 60Hz - it keeps around 62~63 frames-per-second (62.5 is the result). The function to request a 60Hz refresh (request_refresh_rate(60)) doesn't work, even if the Windows monitor is set to 60Hz, Allegro keeps displaying 70Hz of refreshing.
- There's only the milisecond as precision? No turn arounds? Yes, my system is Windows XP, using MinGW + Dev-Cpp.
1) Show us your initialization code.
2) Are you using vsync?
3) What's the result of get_refresh_rate()?
4) You won't ever get exactly the logic or refresh rate you requested. The timers only have so much precision, and in any non-real-time system you will have interference from other processes.
Might be helpful to see the main loop, too.
- I use exactly what extimer.c does. Anyway, I get 62~63 FPS, but the get_refresh_rate() still returns 60, the retrace count returns 71~72 at every sync. No, I don't use vsync(), but this...
1 | //TIMER CONTROL |
2 | //============= |
3 | volatile int update_count = 0; |
4 | volatile int frame_count = 0; |
5 | volatile int fps = 0; |
6 | |
7 | void gfx_timer_proc(void) |
8 | { |
9 | update_count = 1; |
10 | } |
11 | |
12 | END_OF_FUNCTION(gfx_timer_proc) |
13 | |
14 | static void gfx_fps_proc(void) |
15 | { |
16 | fps = frame_count; |
17 | frame_count = 0; |
18 | } |
19 | |
20 | |
21 | /* inits timer |
22 | */ |
23 | void gfx_init_timer() |
24 | { |
25 | LOCK_VARIABLE(update_count); |
26 | LOCK_VARIABLE(frame_count); |
27 | LOCK_VARIABLE(fps); |
28 | LOCK_FUNCTION(gfx_timer_proc); |
29 | LOCK_FUNCTION(gfx_fps_proc); |
30 | |
31 | install_int_ex(gfx_timer_proc, BPS_TO_TIMER(60)); |
32 | install_int_ex(gfx_fps_proc, BPS_TO_TIMER(1)); |
33 | } |
34 | |
35 | void refresh_screen() |
36 | { |
37 | while(0 == update_count) { |
38 | rest(0); |
39 | } |
40 | update_count = 0; |
41 | frame_count++; |
42 | |
43 | //blit the current image buffer |
44 | // source, destiny, sx, sy, dx, dy, sizex, sizey |
45 | blit(video->Bmp_eagle,screen,0,0,video->x,video->y,video->xmax,video->ymax); |
46 | } |
- The refresh_screen() is called when an entire PPU frame is done. Things run around 110 FPS with no control, of course. Anything more?
Three things.
1. request_refresh_rate() needs some work. I've never seen it work properly on Windows.
2. Even if you successfully request the refresh rate you want, it will never be exactly the same every time. No matter what, your Allegro timer will slowly drift away from the monitor's refresh. The only ways you can time perfectly to the monitor is to use vsync(), page flipping (which also uses vsync()) or learn triple buffering.
3. Timing only to the monitor is a very bad idea since not every user will have the same refresh rate and since request_refresh_rate() isn't reliable. If you want your game to be timed accurately you will need to resort to a timer. Thus, unless you're doing real-time logic, monitor synchronization plus accurate game timing are impossible to combine without frame loss.
--- Kris Asick (Gemini)
--- http://www.pixelships.com
1) You're not showing us how you set up your graphics mode.
2) That's now how you synchronize updates to the refresh rate. Use vsync().
Fair enough, here...
1 | /* install gfx |
2 | */ |
3 | int init_gfx() |
4 | { |
5 | int directx_vmode[10] = { |
6 | /*00*/ GFX_AUTODETECT, |
7 | /*01*/ GFX_AUTODETECT_FULLSCREEN, |
8 | /*02*/ GFX_AUTODETECT_WINDOWED, |
9 | /*03*/ GFX_SAFE, |
10 | /*04*/ GFX_DIRECTX_ACCEL, |
11 | /*05*/ GFX_DIRECTX_SOFT, |
12 | /*06*/ GFX_DIRECTX_SAFE, |
13 | /*07*/ GFX_DIRECTX_WIN, |
14 | /*08*/ GFX_DIRECTX_OVL, |
15 | /*09*/ GFX_GDI |
16 | }; |
17 | |
18 | /* Allows to run in background, sweet! |
19 | */ |
20 | set_display_switch_mode(SWITCH_BACKGROUND); |
21 | |
22 | set_color_depth(16); |
23 | request_refresh_rate(60); |
24 | if(0 != set_gfx_mode(directx_vmode[video->gfx_card],video->vx,video->vy,0,0)) |
25 | { |
26 | allegro_message("Graphics error: %s.\n", allegro_error); |
27 | return -1; |
28 | } |
29 | if (get_refresh_rate() != 60) |
30 | allegro_message("Couldn't set refresh rate to 60Hz!"); |
31 | |
32 | /* gfx interpolation requires 640x480 |
33 | */ |
34 | video->Bmp_eagle = create_bitmap_ex(16,640,480); |
35 | surface_lim = (short *)video->Bmp_eagle->line[0]; |
36 | |
37 | /* reset video context |
38 | */ |
39 | fps_display = 1; |
40 | reset_xyblit(); |
41 | ppu_select_palette(0); |
42 | return 0; |
43 | } |
- I use a config file, where the user can specify a gfx mode and a resolution. I gathered all those variables into a structure.
video->gfx_card selects a video mode, even with the poor "card" label though, since it's not a card anyway.
video->vx,video->vy defines the size of the screen, like 640 480.
- The other stuff does not affect the gfx, except for the 16-bit mode indexed by a palette array.