Unsupported virtual resolution
Danikaze

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? :-/

Jonatan Hedborg

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).

Damian Yerrick

Are system bitmaps significantly slower than ordinary bitmaps?

Danikaze

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];
}

Milan Mimica

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

Quote:

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.

Danikaze

Thanks!

But then... how double buffering is made?

Vanneto

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!

Milan Mimica

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.

Danikaze

So... If I have understood (I don't think so), double buffering is doing in this way:

// creates buffer
buffer = create_bitmap(SCREEN_W, SCREEN_H);

// draws the frame into the buffer
draw_something_into_buffer(..);
draw_something_into_buffer(..);
draw_something_into_buffer(..);

// blit the buffer into the screen
blit(buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);

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 ^_^'

Audric

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.

Danikaze

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" :P):

global variables:

#ifdef PAGE_FLIP
  static BITMAP* pantalla_buffer[2];
  static int pantalla_actual;
#endif

function to init graphics:

1int 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
}

Vanneto

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
12ScreenUpdate *scr = new ScreenUpdate();
13 
14// Then init
15scr->init();
16 
17// Use scr->get_buffer() as the drawing surface
18draw_sprite(scr->get_buffer(), mysprite, x, y);
19 
20// Then when you want to blit the buffer to the screen, use update()
21scr->update();
22 
23// To change the buffering mode at runtime, do it like this
24scr->deinit();
25scr = NULL;
26 
27// Now set the buffering mode to double buffer
28scr = new double_buffer();
29 
30//-------------------------------------------
31// If you want to have a triple buffer or pageflipping, just
32// use the appropriate class on init
33ScreenUpdate *scr = new triple_buffer();
34// or
35ScreenUpdate *scr = new pageflipping();

Class(es) attached.

P.S. The classes dont do error checking. :P

Danikaze

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 :)

Thread #593469. Printed from Allegro.cc