Hi! I'm using a combination of page flipping and double buffering. I'm trying to use pageflip for background scrolling and Double buffering for drawing all the sprites, bullets, etc. However, my screen seems to flicker so much. I don't know what I'm doing wrong... Here are my classes, I hope you could help me. Thanks!

if ( p->isHostile() && !( ship->isRecovering() ) )
{
/* check if ship collides projectile instead of
projectile collides ship because ship provides
a more precise collision that a player would not
get annoyed with
*/
if ( ship->collides(p) )
{
ship->takeDamage(10); //change this to projectile power
p->makeInactive();
}
}

This is not proper page flipping. You blit the bitmap AND flip. This is not right.There are, basically, two double buffering approaches you can implement here - blitting the back buffer, or flipping.If you go the blitting route, you would first create a bitmap as the back buffer; each frame, you render the scene to the back buffer, and then use blit() to copy the pixels to the screen.In page flipping, you don't touch "screen" at all. Instead, you create TWO memory bitmaps, A and B. Set A as the front buffer by calling show_video_bitmap() on it, and render your scene to B. When you're done, swap the buffers: call show_video_bitmap() on B, which will be displayed instantly, and render the next frame to A (which will be invisible). The idea behind this is not to copy pixel data, but to change the video memory location from which the hardware's DAC reads pixels.

And by rendering, you mean calling draw_sprite() and probably drawing on the BITMAP returned by create_video_bitmap? Thanks!

Rendering your scene. I don't know what else to call it. Draw all the sprites and lines and whatnot, basically everything you want to display, to the back buffer, not to the screen. Most likely, this will involve draw_sprite(), but it doesn't have to. That's what frame buffering is all about: Since you cannot draw all objects at once, the user would normally be able to watch you drawing the scene: First, the background would appear, then the tile map, then some characters, and finally, some overlay like score, level, text, health bars etc. You don't want this, because it looks ugly. So you draw to an invisible buffer instead, and when you're done drawing everything, you make the contents of the buffer visible in one go - either by copying the pixel data with a call to blit(), or by changing the location the video hardware reads from (show_video_bitmap()).

Thank you, I've been reading TFM for several hours now. I just wanted to be sure and that's why I asked. Now, I tried changing from video bitmap to memory bitmap as you said. However, it doesn't show anything on the screen. When I use video bitmaps, the background overlaps all other sprites. But I'm sure I'm rendering and drawing the background first. You can see my trial-and-error stuff through comments here in my code. I also made a variable called frameCounter so I'd be changing the buffer on which to draw on in its every increment. Thanks!

I didn't bother to read through your source, so sorry if this isn't helping. Anyway, there's a gereat article on page flipping in the wiki: http://wiki.allegro.cc/Page_flipping. I suggest you read through that and see if it helps at all.

Tobias: I think you had initially confused Armond because you said to use show_video_bitmap() on memory bitmaps:

Quote:

Instead, you create TWO memory bitmaps, A and B. Set A as the front buffer by calling show_video_bitmap() on it...

Armond: The two simplest ways to render to the screen are Double Buffering and Page Flipping.

Double Buffering allows you to take certain liberties you can't with Page Flipping, such as not syncing to the monitor refresh rate and being able to render to the buffer at any point in time. Page Flipping has the advantage of taking less CPU time and being smoother.

To Double Buffer, all you need to do is have a regular bitmap to draw on as your buffer, and then you blit that to the screen at the end of your game loop. You don't need to ever call the acquire or release commands using this approach. You can also add the vsync() command to just before the blit to potentially improve the smoothness of the display. (However, poor timer logic or a slow computer may degrade performance when using vsync().)

To Page Flip, you need to make three BITMAP pointers. Two will be video bitmaps made with create_video_bitmap(), the third will be a reference pointer which swaps between the other two video pages every frame. You must group all of your drawing to the reference bitmap into one chunk that lies between acquire and release commands for the reference bitmap. Once you render everything and release the reference bitmap, call show_video_bitmap() on the reference pointer, then switch the reference pointer to the alternate video bitmap. (Thus the video bitmap you draw to "flips" every frame.)

Two things to note when you do Page Flipping:

1. By default, show_video_bitmap() will automatically vsync. You can disable this behaviour, but then the resulting display quality really isn't much better than Double Buffering.

2. The very first video bitmap you make with create_video_bitmap() will almost certainly use the same video memory as the screen. (Not really a problem, it just means if you're going to put more stuff in video memory than the video pages you should probably define the video pages first.

Hope that helps.

I personally recommend double buffering because bad things can happen if you do too much stuff between an acquire/release pair. (And because page flipping + Allegro != working properly on my particular computer.)

I'd do away with the acquire/releases altogether. They're not actually needed, and mainly just increase the risk of you fucking up somewhere further down the line.

True for Double Buffering, not true for Page Flipping, since in Page Flipping you render everything directly to video memory. (Thus if you removed the acquire and release commands there, video memory would have to be locked and unlocked for every single call to draw something to video memory. This is why you can remove them with double buffering, since you generally only need to make one render to video memory (the screen) per frame that way.)

Unless of course you combine double buffering with page flipping, but then you're just wasting CPU time and eliminating the speed boost page flipping provides.

DirectX, in all its glory, is made in such a way that in order to successfully write to video memory that memory must first be locked so that Windows doesn't mess with it while a write is happening. This memory lock takes a good amount of CPU time to engage, and while it's active, making any kind of system call can do bad things.

Allegro controls the state of this lock with its acquire and release commands. Because video memory must be locked in order to draw to it, Allegro will automatically lock and unlock video memory when you draw to it if you haven't locked it already.

So long as you only make one video memory draw per frame, using acquire and release doesn't save you any time.

But, when doing proper page flipping, ALL rendering is happening direct to video memory, which means if you don't enclose all those functions within an acquire/release pair, video memory will be locked and unlocked for every single call to stuff like putpixel, blit, draw_sprite, etc... which will eat CPU time.

If you're rendering everything to a buffer, blitting that to video memory and then doing a page flip, that's essentially combining double buffering with page flipping, which doesn't give you the speed benefits page flipping is supposed to provide.

Tobias: I think you had initially confused Armond because you said to use show_video_bitmap() on memory bitmaps:

You are, of course, right. That is utter nonsense I wrote there.

Armond:I haven't really read all of your code there, but on first glance, it looks as if you were allocating the frame buffers inside the background class, which doesn't look right to me. The background is just one of many objects that draw something onto the back buffer; it has no business with the underlying mechanics of the frame buffering system.IMO, you should split your code up into the following overall modules (no matter what the genre):- A framebuffer module that handles setting up, flipping, and shutting down the frame buffering system. You can either make two classes with the same interface for memory-blitting and page flipping, or one class that can do both. Either way, the public interface should look something like this:

class cFramebuffer {// protected / private members left out.
public:
cFramebuffer(int buffer_method = MEMORY_BLIT);// The parameter is only needed if you put all buffer methods into the same class.// Otherwise, each buffering method would have its own constructor.// If you have a dedicated class for each buffering method, the member funcs below// need to be virtual.
~cFramebuffer();void flip();// takes the appropriate action depending on the buffer method used.BITMAP* get_backbuffer();constchar* get_buffer_mode_desc()const;// optional, and useful mainly for debugging purposes;};

Of course, this doesn't have to be a class; were you using plain C, you'd just provide the plain functions in the header and use static variables in the .c file. In C++, though, a class is a much better choice.If you want to go all fancy, make the framebuffer class a singleton, but I suggest you don't do that for now. The key here is ENCAPSULATION: make sure that nothing except the frame buffer module itself ever touches the internal buffers directly - only through the get_backbuf() method. This gives you more control over who draws what and where to.- A game module that manages your objects, scene, backgrounds, timing, etc. - pretty much everything that is in-game. For drawing, it first calls the global framebuffer's get_backbuffer() method, draws everything to the bitmap it provides (typically calling its sub-modules' draw() methods), and finally calls framebuffer->flip(). The game module should - at least for more complex games - be split up into more modules, e.g. one for the background, one for characters, one for timing, etc. A typical drawing routine might look like this:

cGame::draw(){// note that this method does not know which frame buffering method is being used.BITMAP* backbuf = framebuffer->get_backbuffer();// get a valid back buffer from the framebuffer moduleassert(backbuf);// make sure we really have a back buffer!// OK, now draw our scene back-to-front:
background->draw(backbuf, scroll_x, scroll_y);for(int i =0; i < num_actors;++i)
actor<i>->draw(backbuf, scroll_x, scroll_y);// if you want to display overlay like scores, health bars, etc., here's the place
framebuffer->flip();// Tell the framebuffer module we're done with this frame.}

- A "main" module that sets up allegro, creates a global frame buffer object, spawns the game module, and finally cleans up by destroying the game and frame buffer objects and exiting allegro.

The nice thing about this approach is that once you have one frame buffering system ready to go, the interface can be reused, so if you later want to add another option, you only need to change the frame buffer module, and add a few lines to the main module, while all the other modules can remain unchanged.

Really? So what is "a good amount", I mean, I've never used the acquire/release calls anywhere and I've never ran into any problems.

"A good amount" can be anywhere from near instantanious to several tens to hundreds of milliseconds, or more. Since it involves a mutex lock, if something else is holding that lock, your program will pause until the lock becomes free. There could be other factors involved too.. I'm not very familiar with the Windows code.

But as mentioned, as long as you draw to the screen/video bitmaps, the screen must be acquired no matter what. And if all you do is blit a memory buffer to the screen, there's nothing to gain since Allegro will acquire for you.

-- "Do not meddle in the affairs of cats, for they are subtle and will pee on your computer." -- Bruce Graham

But as mentioned, as long as you draw to the screen/video bitmaps, the screen must be acquired no matter what. And if all you do is blit a memory buffer to the screen, there's nothing to gain since Allegro will acquire for you.

Yeah, I know. I'd just like to know what kind of speed differences we're talking about.

Kauhiz: It is dependent on a number of factors, but the speed difference can be insane if you do enough writes.

For instance, if you draw 200 objects directly to the screen on one update, but fail to call the acquire and release commands first, those 200 objects will each call those commands themselves. Thus instead of one locking operation you suddenly have 200.

And again, this is only if you do all of your drawing directly to video memory. If you draw everything to a memory buffer then blit that to video memory, the lock is only engaged once because regular bitmaps don't need to be locked to be written to.

Kauhiz: We're helping you perfectly fine, you just don't like our answers. You want to know exactly what factors go into the delay of locking a video bitmap. The trouble is, everything is a factor. The speed of the computer, the speed of the video card, the speed of your RAM, the speed of the video RAM, the state of your CPU registers... no matter what computer you are on the lock can take anywhere from an insignificant amount of CPU time to a rather large amount of CPU time to engage. There's absolutely no way to calculate or control it so there's no sense trying to.

All you need to understand is that locking and unlocking a video bitmap multiple times in one frame is slower than locking and unlocking once per frame. By how much? There's no way to know until you do it.

Thank you people. I think you've done everything you can to help this poor fella. It's up to me now to incorporate your ideas with my code. If I succeed, I'll get back at you and post the working code. Thanks!