Please support our sponsor:
DirectX4VB.Com - All You Need For Multimedia Visual Basic Programming

Main Site Links Resources Tutorials
News VB Gaming Code Downloads DirectX 7
Contact Webmaster VB Programming Product Reviews DirectX 8
  General Multimedia Articles DirectX 9
      Miscellaneous

 

DirectDraw: Flipping Chains
By: Jack Hoxley
Written: May 2000


You will only have come across flipping very briefly, as it only takes one line of code in a directdraw application. Despite it being quite a small piece (code wise) it is actually one of the most important parts of a directdraw application. Flipping is where it copies everything you've just drawn on the backbuffer to the primary buffer (and therefore appearing on screen). There are several things that you can change to adjust how the flipping process works.

First off you must understand what happens when you flip the backbuffer. Normally you're application will be double buffered, only windowed mode can be run single-buffered. Double buffered means that there are two surfaces, the primary and the backbuffer; Every time you flip the surfaces DirectDraw swaps the memory round, the backbuffers data appears on the primary buffer and the primary buffer's data appears on the back buffer:

A B
B A
A B

If you think of A and B as being two images - A being blank (nothing) and B being a proper picture. In stage 1, the primary buffer is A and the Backbuffer is drawn to, therefore it will now have an image in it (B). The second stage sees the image on the backbuffer flipped to the primary buffer, and we would now be seeing the picture (B), and at the same time the backbuffer would now be empty (A). The third sees the cycle begining again, this time the primary buffer has what was just composed on the backbuffer (in step 2) and the back buffer has what was just displayed on screen (in step 2).

In real terms, as far as you're concerned, whilst the back buffer is being flipped to the primary buffer you're application is busy. It is not doing anything - you've sent your message to DirectDraw, and whilst it's doing it your application is idle. In an ideal world you'd want to get straight on with drawing the next frame, so that as soon as the current frame has been flipped you can flip again. One particular way of doing this is called tripple buffering, more later on this.

You may have noticed that there is a flag at the end of the flip statement - this can be changed to suit you. This table summarises what they all do, and if their useful to you.

Flag Meaning
DDFLIP_DONOTWAIT If you want to keep drawing whilst the flip is pending, use this flag. This doesn't offer any great speed advantage.
DDFLIP_EVEN This is used when displaying video on an overlay surface. It will not be of any use normally.
DDFLIP_INTERFVAL2 DirectDraw flips on the second vertical refresh of the screen.
DDFLIP_INTERFVAL3 DirectDraw flips on the third vertical refresh
DDFLIP_INTERFVAL4 Directdraw flips on the fourth vertical refresh
DDFLIP_NOVSYNC Allows DirectDraw to flip faster than the monitors refresh rate, but may introduce video artifacts
DDFLIP_ODD This is similiar to the DDFLIP_EVEN flag, and is only used when displaying video on overlay surfaces.
DDFLIP_WAIT This is the default flag. This forces DirectDraw to wait until the flipper is free if it is busy. This is rock-solid, and will not miss a single frame - but may well slow down because of this.
DDFLIP_STEREO When this is set, the primary buffer becomes the main stereo buffer, and the backbuffers are the Left and Right stereo surfaces. The hardware then flips between the left and right on every screen refresh. This is hardware dependent.

 

You may well find that some of the above flags improve performance, but it is unlikely that they will produce an significant speed increase.

Tripple Buffering
As mentioned earlier this is the best way of increasing speed. The good thing is that it's not very hardware dependant and that it is incredibly easy to implement. Whereas before you will have used two buffers, a primary buffer and a back buffer; when using tripple buffering you have a primary buffer and two back buffers.

Normally you have to wait for the flip to be completed before you can start working on the next frame; tripple buffering allows you to start working on the next frame whilst DirectDraw is still flipping the previous frame. Because of this you can achieve a sometimes dramatic speed increase, on my main computer it goes from 60fps to 84fps, and it isn't a top-of-the-range 3D card either (Savage4 Pro).

The two things you have to bare in mind are memory and number of buffers. You may well be fooled into thinking that if three buffers are faster than two, four buffers will be faster than three. Not true. Using any more than three buffers in the flipping chain will do the opposite and start to slow your program down. This is down to memory. If a 640x480 buffer takes up 320kb (roughly), then 2 surfaces will take up 640kb (the normal chain) and three buffers will take up 960kb. The more you add, the more memory you will need; and the more memory you use up the slower things will get; it's fairly obvious when you think about it.

Tripple buffering can be visualised as shown in these two diagrams:

This first picture is a normal flipping chain, showing the backbuffer linking to the primary buffer

This second picture shows two backbuffers linked seperately to the primary buffer.

Whilst Buffer 1 is busy, buffer 2 is not busy; and therefore can be blitted to. This is better shown in the following diagram:

This pattern will keep repeating itself, so only three frames are shown. The flipping sequence can also be demonstrated by this following diagram:

A B C
{- -- --
B C A
C A B

For every frame the current image is moved along one.

So, How do I do this?
Hopefully now you understand how it works; the code is very simple, and is shown below:

'First you create the primary, specifying 2 attached surfaces
ddsd1.lFlags = DDSD_CAPS Or DDSD_BACKBUFFERCOUNT
ddsd1.ddsCaps.lCaps = DDSCAPS_PRIMARYSURFACE Or DDSCAPS_FLIP Or DDSCAPS_COMPLEX
ddsd1.lBackBufferCount = 2 'This would normally be '1'
Set primary = dd.CreateSurface(ddsd1)

'Then we retrieve pointers to the backbuffer. You only need one;
'as directdraw sorts out which one you're drawing to - so you always
'Draw to the same object.

Dim caps As DDSCAPS2
caps.lCaps = DDSCAPS_BACKBUFFER
Set backbuffer = primary.GetAttachedSurface(caps)
backbuffer.GetSurfaceDesc ddsd3

Simple! It would be advised to let the user decide which mode they want - A card with little memory will not be able to use tripple buffering to it's advantage (it would slow down rather than speed up). If you wanted to automate this you could check the amount of available video memory (see Enumeration) and then make a decision based on that information.

The Retained Mode program has a facility to use Tripple buffering, and it is quite obvious the speed advantage.

DirectX 4 VB © 2000 Jack Hoxley. All rights reserved.
Reproduction of this site and it's contents, in whole or in part, is prohibited,
except where explicitly stated otherwise.
Design by Mateo
Contact Webmaster
This site is hosted by Exhedra Solutions, Inc., the parent company of RentACoder.com and PlanetSourceCode.com