Tricks of the Windows Game Programming Gurus:Advanced DirectDraw and Bitmapped Graphics

All ITKnowledge Source Code Search Tips Advanced Search |

| Tricks of the Windows Game Programming Gurus by Andre LaMothe Sams, Macmillan Computer Publishing ISBN: 0672313618 Pub Date: 09/27/99

Search this book:

Previous | Table of Contents | Next

Also, note the boldfaced code from `Game_Main()` that deals with the lock window_closed, reprinted here:

    // make sure this isn’t executed again

    if (window_closed)

       return(0);

    // for now test if user is hitting ESC and send WM_CLOSE

    if (KEYDOWN(VK_ESCAPE))

       {

       PostMessage(main_window_handle,WM_CLOSE,0,0);

       window_closed = 1;

       } // end if

I needed to add the exit state in the preceding code because it’s possible that `Game_Main()` will be called one extra time even though the window was destroyed. This will cause an error, of course, because DirectDraw anchors to the window handle. Hence, I have created a locking variable (or binary semaphore if you will) that’s set once the window is closed, and the gate keeps the `Game_Main()` function from any future entry. This is a very important detail that I should have mentioned in the last program, but I didn’t. Of course, I could have rewritten the text, but I just wanted to show you how easy it is to make a mistake with DirectX/Win32 asynchronous programming.

That’s about all there is to page flipping. DirectDraw does most of the work, but I want to leave you with some last details about it. First, when you create a back buffer, there is the possibility that DirectDraw will create it in system memory rather than VRAM (if there isn’t any left). In that case, you don’t have to do anything; DirectDraw will emulate the functionality of page flipping with double buffering and copy the back buffer to the primary surface when you make a call to `Flip()`. However, it will be slower. The cool thing is that your code will work no matter what. So that’s pretty killer and drama-free, baby!

> Note: In general, when you create the primary and secondary back buffer, you want them both in VRAM. The primary is always in VRAM, but it’s possible to get stuck with a system memory back buffer. However, always remember that there’s only so much VRAM, and you might want to forgo the use of a VRAM back buffer in exchange for putting all your game graphics in VRAM to speed the blitting of images. Using the hardware blitter to move bitmaps from VRAM to VRAM is much faster than moving them from system memory to VRAM. Alas, you might decide to make a system memory back buffer in cases where you have a lot of small sprites or bitmaps and you’re going to do a lot of blitting. In this case, you’re doing so much blitting, the speed loss of a double buffer scheme in deference to page flipping with a VRAM animation system is far outweighed by the performance gain of having all your game bitmaps in VRAM.

### Using the Blitter

If you’ve been programming in DOS, not only have you been stuck in a quasi-32-bit world (even with a DOS extender), but I’ll bet you’ve never been able to use hardware acceleration for 2D/3D graphics without a driver from the manufacturer or a fat third-party library. Hardware acceleration has been around since way before DOOM, but game programmers could rarely use it because it was more of a Windows thing. However, with DirectX you can take total advantage of all acceleration—graphics, sound, input, networking, etc. But the coolest thing is finally being able to use the hardware blitter to move bitmaps and do fills! Let me show you how it works…

Normally, when you want to draw a bitmap or fill a video surface, you have to do it manually, pixel by pixel and so forth. For example, take a look at Figure 7.13, which depicts an 8×8, 256-color bitmap. Imagine that you want to copy this image to a video or offscreen buffer at position (x,y) that’s 640×480 with linear pitch. Here’s the code to do it:

    UCHAR *video_buffer; // points to VRAM or offscreen surface

    UCHAR bitmap[8*8];  // holds our bitmap in row major form

    // crude bitmap copy

    // outer loop is for each row

    for (int index_y=0; index_y<8; index_y++)

        {

        // inner loop for each pixel of each row

        for (int index_x=0; index_x<8; index_x++)

            {

            // copy the pixel without transparency

             video_buffer[x+index_x + (y+index_y)*640] =

                         bitmap[index_x + index_y*8];

            } // end for index_x

        } // end for index_y

Figure 7.13 An 8×8, 256-color bitmap.

Now take a few minutes (or seconds, if you’re a cyborg) and make sure you completely understand what’s going on and could write this yourself without looking. Refer back to Figure 7.13 to help visualize it. Basically, you’re simply copying a rectangular bitmap of pixels from one place in memory to another. There are obviously a number of optimizations and problems with this function. First, I’ll talk about the problems:

  Problem 1: The function is incredibly slow.
  Problem 2: The function doesn’t take into consideration transparency, meaning that if you have a game object in the bitmap that has black around it, the black will be copied. This problem is shown in Figure 7.14. You need to add code for this.

Figure 7.14 Transparent pixels aren’t copied to the destination surface during blitting.

As far as optimizations go, you can do the following:

  Optimization 1: Get rid of all the multiplication and most of the addition by precomputing starting addresses in the source and destination buffers and then increment pointers for each pixel.
  Optimization 2: Use memory fills for nontransparent runs of pixels (advanced).

Previous | Table of Contents | Next

Copyright © Macmillan Computer Publishing, Inc.

Products | Contact Us | About Us | Privacy | Ad Info | Home
Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.