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

`dwX` and `dwY` are the (x,y) coordinates to blit to on the destination surface.

`lpDDSrcSurface` is the address of the `IDIRECTDRAWSURFACE4` interface for the DirectDraw surface to be used as the source of blit.

`lpSrcRect` is the address of the source `RECT` that defines the upper-left and lower-right points of the rectangle to blit from on the source surface.

`dwTrans` is the type of blitter operation. Table 7.4 shows the possible values.

Table 7.4 Control Flags for `BltFast()` Blitter Operation

Value | Description
--- | ---

`DDBLTFAST_SRCCOLORKEY` | Specifies a transparent blit that uses the source’s color key.
`DDBLTFAST_DESTCOLORKEY` | Specifies a transparent blit that uses the destination’s color key.
`DDBLTFAST_NOCOLORKEY` | Specifies a normal copy blit with no transparency. Could be faster on some hardware; definitely faster in HEL.
`DDBLTFAST_WAIT` | Forces the blitter to wait while busy and not send back the `DDERR_WASSTILLDRAWING` message. `BltFast()` returns as soon as the blit can be performed, or a serious error occurs.

(Note that I’ve boldfaced the most useful flags.)

All right, the first question is, “Why are there two different blitter functions?” The answer should be apparent from the functions themselves: `Blt()` is the full-blown kitchen sink model, while `BltFast()` is simpler but has fewer options. Furthermore, `Blt()` uses DirectDraw clippers while `BltFast()` doesn’t. This means that `BltFast()` is faster than `Blt()` in the HEL by about 10%, and may even be faster in hardware (if the hardware is crappy and sucks at clipping). The point is, use `Blt()` if you need clipping, and use `BltFast()` if you don’t.

Let me show you how to use the `Blt()` function to fill a surface. This will be reasonably simple because there isn’t a source surface (only a destination surface). A lot of the parameters, therefore, can be `NULL`. To do a memory fill, you must perform the following steps:

  1. Place the color index or RGB-encoded color you want to fill the surface with in the `dwColorFil0 l` field of a `DDBLTFX` structure.
  2. Set up a `RECT` structure with the area that you want to fill on your destination surface.
  3. Make a call to `Blt()` from the destination surface’s `IDIRECTDRAWSURFACE4` interface pointer with the control flags `DDBLT_COLORFILL | DDBLT_WAIT`. This is very important; `Blt()` and `BltFast()` are both called from the destination surface’s interface, not the source!

Here’s the code to fill a region of an 8-bit surface with a color:

    DDBLTFX ddbltfx; // the blitter fx structure

    RECT dest_rect;  // used to hold the destination RECT

    // first initialize the DDBLTFX structure

    DDRAW_INIT_STRUCT(ddbltfx);

    // now set the color word info to the color we desire

    // in this case, we are assuming an 8-bit mode, hence,

    // we'll use a color index from 0-255, but if this was a

    // 16/24/32 bit example then we would fill the WORD with

    // the RGB encoding for the pixel - remember!

    ddbltfx.dwFillColor = color_index;

    // now set up the RECT structure to fill the region from

    // (x1,y1) to (x2,y2) on the destination surface

    dest_rect.left   = x1;

    dest_rect.top    = y1;

    dest_rect.right  = x2;

    dest_rect.bottom = y2;

    // make the blitter call

    lpddsprimary->Blt(&dest_rect, // pointer to dest RECT

                  NULL, // pointer to source surface

                  NULL, // pointer to source RECT

                  DDBLT_COLORFILL | DDBLT_WAIT,

                  // do a color fill and wait if you have to

                  &ddbltfx); // pointer to DDBLTFX holding info

> Note: There’s one little detail with any of the `RECT` structures that you send to most DirectDraw functions: In general, they’re upper-left inclusive, but lower-right exclusive. In other words, if you send a `RECT` that’s (0,0) to (10,10), the actual rectangle scanned will be (0,0) to (9,9) inclusive. So keep that in mind. Basically, if you want to fill the entire 640×480 screen, you would send upper-left as (0,0) and lower-right as (641, 481).

The important things to notice are the setup and that both the source surface and `RECT` are `NULL`. This makes sense because you’re using the blitter to fill with a color, not to copy data from one surface to another. Okay, let’s move on, my little leprechaun.

The preceding example was for an 8-bit surface; the only change you need to make for a high-color mode in 16/24/32-bit mode is to simply change the value in `ddbltfx.dwFillColor` to reflect the pixel value that you want the fill to be performed in. Isn’t that cool?

For example, if the display happened to be a 16-bit mode and you wanted to fill the screen with green, the following code would work:

    ddbltfx.dwFillColor = _RGB16BIT565(0,255,0);

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.