Hello everybody!
I'm coding in Linux, and testing my progress in Windows too.
When I set up graphic modes, I use this:
set_gfx_mode(GFX_AUTODETECT_WINDOWED, w, h, w*2, h)
It works perfectly on Linux, but I get an error on Windows:
"Unsupported virtual resolution".
Is there any restriction on sizes for virtual resolution?
I used w*2, h to make a double buffering (flipping with show_video_bitmap) and it works on Linux.
If I try with set_gfx_mode(GFX_AUTODETECT_WINDOWED, w, h, 0, 0) on Windows, it goes ok, but slow.
It seems not to do double buffering right...
Any suggestion?
You pretty much don't use the virtual screen nowadays.
Just create a video bitmap if you want to do some form of double buffering (though i would recommend using a regular bitmap, as drawing/reading to/from the screen is slow).
Are system bitmaps significantly slower than ordinary bitmaps?
Jonathan
That's what I was doing, but to create video bitmaps in Linux, I need to have enough memory :S
That's how I made double buffering:
Initializing:
if(set_gfx_mode(GFX_AUTODETECT_WINDOWED, w, h, w*2, h)==0) {; pantalla_buffer[0] = create_video_bitmap(SCREEN_W, SCREEN_H); pantalla_buffer[1] = create_video_bitmap(SCREEN_W, SCREEN_H); pantalla_actual = 0; pantalla = pantalla_buffer[pantalla_actual]; fps_frame_time = (fps == 0)? 0 : 1000/fps; } else { allegro_message("Error: %s\n", allegro_error); }
Flipping function:
void flip() { show_video_bitmap(pantalla); pantalla_actual = (pantalla_actual+1)%2; pantalla = pantalla_buffer[pantalla_actual]; }
Use this:
#ifdef ALLEGRO_VRAM_SINGLE_SURFACE set_gfx_mode(GFX_AUTODETECT_WINDOWED, w, h, w*2, h) #else set_gfx_mode(GFX_AUTODETECT_WINDOWED, w, h, 0, 0) #endif
f I try with set_gfx_mode(GFX_AUTODETECT_WINDOWED, w, h, 0, 0) on Windows, it goes ok, but slow.
It seems not to do double buffering right...
Keep in mind that reading from video bitmaps is very slow.
And that's page flipping what you're doing, not double buffering.
Thanks!
But then... how double buffering is made?
You draw everything onto a sourface, the buffer, that is stored in memory. Then in the end you draw the buffer to the screen.
Drawing:
PlayerSprite --> Buffer
SometinSprite --> Buffer
Buffer --> Screen
Easy!
In double buffering you draw something onto the buffer (in allegro, that's usually a memory bitmap) and then blit the contents of the buffer to the screen. This can be faster then page flipping if you are using transparency because reading from allegro's video bitmaps is slow.
In page flipping you draw onto one page of video memory and then "flip" the pages to display the page you were previously drawing to. I can be faster then double buffering because no data copying occurs.
So... If I have understood (I don't think so), double buffering is doing in this way:
That's all? Or is it needed 2 buffers to do it?
Does vsync affects in any way this? (Because the thing is make something while the screen is being rendered... or not?)
Sorry for all those questions ^_^'
You got it right.
About vsync():
If you force your blit(on screen) to happen immediately after a vsync(), you're very likely that the complete replacement will happen during the interval, so the user will see the previous image, then the next image, and never a mix of the two : it prevents shearing effects.
However the vsync() function does not have a precise timing, forces a wait, and is based on busy-waiting; so it's not all perfect.
After watching replies, I made this, to use page_flip or double buffering depending on PAGE_FLIP directive (sorry for variable names, I'm Spanish, just know "pantalla"="screen" ):
global variables:
#ifdef PAGE_FLIP static BITMAP* pantalla_buffer[2]; static int pantalla_actual; #endif
function to init graphics:
1 | int inicializar_graficos(int w, int h, int z, int fps) { |
2 | int error_init; |
3 | |
4 | set_color_depth(z); |
5 | |
6 | #ifdef ALLEGRO_VRAM_SINGLE_SURFACE |
7 | error_init = set_gfx_mode(GFX_AUTODETECT_WINDOWED, w, h, w*2, h); |
8 | #else |
9 | error_init = set_gfx_mode(GFX_AUTODETECT_WINDOWED, w, h, 0, 0); |
10 | #endif |
11 | |
12 | if(!error_init) { |
13 | #ifdef PAGE_FLIP |
14 | pantalla_buffer[0] = create_video_bitmap(SCREEN_W, SCREEN_H); |
15 | pantalla_buffer[1] = create_video_bitmap(SCREEN_W, SCREEN_H); |
16 | pantalla_actual = 0; |
17 | pantalla = pantalla_buffer[pantalla_actual]; |
18 | #else |
19 | pantalla = create_bitmap(SCREEN_W, SCREEN_H); |
20 | #endif |
21 | fps_frame_time = (fps == 0)? 0 : 1000/fps; |
22 | } else { |
23 | allegro_message("Error: %s\n", allegro_error); |
24 | } |
25 | return !error_init; |
26 | } |
Function to draw in screen:
void flip() { #ifdef PAGE_FLIP show_video_bitmap(pantalla); pantalla_actual = (pantalla_actual+1)%2; pantalla = pantalla_buffer[pantalla_actual]; #else blit(pantalla, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H); #endif }
I made a class some time ago with Mirans help. You can use it to have more buffers whitout changing a lot of code. For example:
1 | // Include buffering.hpp |
2 | #include "buffering.hpp" |
3 | |
4 | // The class is ScreenUpdate |
5 | // The class is extended by double_buffer, triple_buffer and pageflipping |
6 | |
7 | // Use it like this |
8 | |
9 | // Everything will be drawn to screen |
10 | |
11 | // Create a object |
12 | ScreenUpdate *scr = new ScreenUpdate(); |
13 | |
14 | // Then init |
15 | scr->init(); |
16 | |
17 | // Use scr->get_buffer() as the drawing surface |
18 | draw_sprite(scr->get_buffer(), mysprite, x, y); |
19 | |
20 | // Then when you want to blit the buffer to the screen, use update() |
21 | scr->update(); |
22 | |
23 | // To change the buffering mode at runtime, do it like this |
24 | scr->deinit(); |
25 | scr = NULL; |
26 | |
27 | // Now set the buffering mode to double buffer |
28 | scr = new double_buffer(); |
29 | |
30 | //------------------------------------------- |
31 | // If you want to have a triple buffer or pageflipping, just |
32 | // use the appropriate class on init |
33 | ScreenUpdate *scr = new triple_buffer(); |
34 | // or |
35 | ScreenUpdate *scr = new pageflipping(); |
Class(es) attached.
P.S. The classes dont do error checking.
Thanks Vanneto!
Even if I am using C (not C++) so I can't use your classes, and I have the code already implemented, it was very useful so I can check my code is ok now and I could see how the triple buffering is used.
^_^
PS: Thanks to everyone who replied here