Chapter 6. First Contact: DirectDraw

 

Chapter 6. First Contact: DirectDraw

1.Using the Interfaces Together

  • create an IDirectDraw7 interface directly with DirectDrawCreateEx(). Using this interface, set both the cooperation level and video mode.

  • Using the IDirectDrawSurface7 interface, create at least a primary surface to draw on. Based on the color depth of the surface and the video mode itself, a palette will be needed if the video mode is 8 bits per pixel or less.

  • Create a palette using the IDirectDrawPalette interface, initialize it with RGB triples, and attach it to the surface of interest.

  • If the DirectDraw application is going to be windowed, or if you're going to render bitmaps that could potentially go out of bounds of the visible DirectDraw surface, at least create a single clipper and size it to the extents of the visible window.

  • Draw on the primary surface.

2.Error Handling with DirectDraw

   FAILED()      //Tests for failure.
    SUCCEEDED()    //
Tests for success.

Return Code Description
DD_OK Total Success.
DDERR_DIRECTDRAWALREADYCREATED DirectDraw object has already been created.
DDERR_GENERIC DirectDraw has no idea what's wrong.
DDERR_INVALIDDIRECTDRAWGUID The device GUID is unknown.
DDERR_INVALIDPARAMS Something is wrong with the parameters you sent.
DDERR_NODIRECTDRAWHW There isn't any hardware.
DDERR_OUTOFMEMORY Take a wild guess?

3.Creating a DirectDraw Object

  HRESULT WINAPI DirectDrawCreateEx(
      GUID FAR *lpGUID,  // the GUID of the driver, NULL for active display
      LPVOID *lplpDD,    // receiver of the interface
      REFIID iid,       // the interface ID of the interface you are requesting
      IUnknown FAR *pUnkOuter  // advanced COM, NULL
    );

LPDIRECTDRAW7 lpdd; // version 7.0
// create version 7.0 DirectDraw object interface

DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL);

4. Cooperating with Windows

    IDirectDraw7:: SetCooperativeLevel()

    HRESULT SetCooperativeLevel(HWND hWnd, DWORD dwFlags);

Value Description
DDSCL_ALLOWMODEX Allows the use of Mode X (320x200,240,400) display modes. Can be used only if the DDSCL_EXCLUSIVE and DDSCL_FULLSCREEN flags are present.
DDSCL_ALLOWREBOOT Allows Ctrl+Alt+Del to be detected while in exclusive (full-screen) mode.
DDSCL_EXCLUSIVE Requests the exclusive level. This flag must be used with the DDSCL_FULLSCREEN flag.
DDSCL_FPUSETUP Indicates that the calling application is likely to keep the FPU set up for optimal Direct3D performance (single precision and exceptions disabled) so Direct3D does not need to explicitly set the FPU each time. For more information, look up "DirectDraw Cooperative Levels and FPU Precision" in the DirectX SDK.
DDSCL_FULLSCREEN Indicates full-screen mode will be used. GDI from other appli cations will not be able to draw on the screen. This flag must be used with the DDSCL_EXCLUSIVE flag.
DDSCL_MULTITHREADED Requests multithread-safe DirectDraw behavior. Don't worry about this for now.
DDSCL_NORMAL Indicates that the application will function as a regular Windows application. This flag cannot be used with the DDSCL_ALLOWMODEX, DDSCL_EXCLUSIVE, or DDSCL_FULLSCREEN flags.
DDSCL_NOWINDOWCHANGES Indicates that DirectDraw is not allowed to minimize or restore the application window on activation.

5.Getting into the Mode of Things

    IDirectDraw7::SetDisplayMode().

    HRESULT SetDisplayMode(DWORD dwWidth,  // width of mode in pixels
               DWORD dwHeight, // height if mode in pixels
               DWORD dwBPP,    // bits per pixel, 8,16,24, etc.
               DWORD dwRefreshRate, // desired refresh, 0 for default
               DWORD dwFlags); // extra flags (advanced) 0 for default

6.The Subtleties of Color

  • Create one or more palette data structures as arrays of 256 PALETTENTRY's.
  • Create a DirectDraw palette interface IDirectDrawPalette object from the DirectDraw object itself. In many cases, this will be directly mapped to the hardware VGA palette registers.
  • Attach the palette object to a drawing surface, such as the primary surface, so all data rendered to it is displayed in the appropriate colors.
  • Optional) If you desire, you can change the palette entries or the entire palette. You will need to take this step if you sent a NULL palette during step 2 and opted to omit step 1. Basically, what I'm trying to say is that when you create a palette interface, you can send it a palette of color also. But if you don't, you can always do it later. Therefore, step 2 can be step 1 if you remember to fill up the palette entries at a later time.

You must set the peFlags field to PC_NOCOLLAPSE. This is necessary because you don't want Win32/DirectX optimizing your palette for you.

/
PALETTEENTRY palette[256]; // palette storage

// fill em up with color!
for (int color=1; color < 255; color++)
{
// fill with random RGB values
palette[color].peRed = rand()%256;
palette[color].peGreen = rand()%256;
palette[color].peBlue = rand()%256;

// set flags field to PC_NOCOLLAPSE
palette[color].peFlags = PC_NOCOLLAPSE;
} // end for color

// now fill in entry 0 and 255 with black and white
palette[0].peRed = 0;
palette[0].peGreen = 0;
palette[0].peBlue = 0;
palette[0].peFlags = PC_NOCOLLAPSE;

palette[255].peRed = 255;
palette[255].peGreen = 255;
palette[255].peBlue = 255;
palette[255].peFlags = PC_NOCOLLAPSE;
/

HRESULT CreatePalette(DWORD dwFlags, // control flags
LPPALETTEENTRY lpColorTable, // palette data or NULL
LPDIRECTDRAWPALETTE FAR *lplpDDPalette, // received palette interface
IUnknown FAR *pUnkOuter); // advanced, make NULL

/
LPDIRECTDRAWPALETTE lpddpal = NULL; // palette interface

if (FAILED(lpdd->CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256 | DDPCAPS_INITIALIZE,
palette, &lpddpal, NULL)))
{
// error
} // end if
/

 

7.Building a Display Surface

    A primary surface directly corresponds to the actual video memory being rasterized by the video card and is visible at all times.

    从表面:a.平滑动画效果:后备缓冲(总是合著表面有相同的BPP和尺寸)、页面切换
            b.保存位图和游戏中表示对象的动画:只有使用DirectDraw显示表面才能调用使用于位图数据的加速硬件。

To create any surface, you must follow these steps:
    a.Fill out a
DDSURFACEDESC2 data structure that describes the surface you want to create.
    b.
Call IDirectDraw7::CreateSurface() to
create the surface.

typedef struct _DDSURFACEDESC2
        {
        DWORD dwSize;   // size of this structure
        DWORD dwFlags;  //
indicate fields you'll be filling or which fields  to retrieve
                         //
DDSD_CAPS
        DWORD dwHeight; // height of surface in pixels
        DWORD dwWidth;  // width of surface in pixels

        union
        {
        LONG  lPitch;        // memory pitch per row,每行的字节数,步幅(stride),内存宽度
        DWORD dwLinearSize;  // size of the buffer in bytes
        } DUMMYUNIONNAMEN(1);
        DWORD dwBackBufferCount;  // number of back buffers chained
        union
        {
        DWORD dwMipMapCount;           // number of mip-map levels
        DWORD dwRefreshRate;           // refresh rate
        } DUMMYUNIONNAMEN(2);
        DWORD  dwAlphaBitDepth;        // number of alpha bits
        DWORD  dwReserved;             // reserved
        LPVOID lpSurface;              // pointer to surface memory
        DDCOLORKEY ddckCKDestOverlay;  // dest overlay color key
        DDCOLORKEY ddckCKDestBlt;      // destination color key
        DDCOLORKEY ddckCKSrcOverlay;   // source overlay color key
        DDCOLORKEY ddckCKSrcBlt;       // source color key
        DDPIXELFORMAT ddpfPixelFormat; // pixel format of surface
        DDSCAPS2   ddsCaps;            // surface capabilities
        DWORD      dwTextureStage;     // used to bind a texture
                                       // to specific stage of D3D
        } DDSURFACEDESC2, FAR* LPDDSURFACEDESC2;

typedef struct _DDSCAPS2
        {
        DWORD    dwCaps;   // Surface capabilities
        DWORD    dwCaps2;  // More surface capabilities
        DWORD    dwCaps3;  // future expansion
        DWORD    dwCaps4;  // future expansion
        } DDSCAPS2, FAR* LPDDSCAPS2;

Value Description
DDSCAPS_BACKBUFFER Indicates that this surface is the back buffer of a surface flipping structure.
DDSCAPS_COMPLEX Indicates that a complex surface is being described. A complex surface is a surface with a primary surface and one or more back buffers to create a flipping chain.
DDSCAPS_FLIP Indicates that this surface is a part of a surface flipping structure. When this capability is passed to the CreateSurface() method, a front buffer and one or more back buffers are created.
DDSCAPS_LOCALVIDMEM Indicates that this surface exists in true, local video memory rather than non-local video memory. If this flag is specified, DDSCAPS_VIDEOMEMORY must be specified as well.
DDSCAPS_MODEX Indicates that this surface is a 320x200 or 320x240 Mode X surface.
DDSCAPS_NONLOCALVIDMEM Indicates that this surface exists in non-local video memory rather than true, local video memory. If this flag is specified, DDSCAPS_VIDEOMEMORY flag must be specified as well.
DDSCAPS_OFFSCREENPLAIN Indicates that this surface is an offscreen surface that is not a special surface such as an overlay, texture, z-buffer, front-buffer, back-buffer, or alpha surface. Usually used for sprites.
DDSCAPS_OWNDC Indicates that this surface will have a device context association for a long period.
DDSCAPS_PRIMARYSURFACE Indicates that this surface is the primary surface. It represents what is visible to the user at the moment.
DDSCAPS_STANDARDVGAMODE Indicates that this surface is a standard VGA mode surface, and not a Mode X surface. This flag cannot be used in combination with the DDSCAPS_MODEX flag.
DDSCAPS_SYSTEMMEMORY Indicates that this surface memory was allocated in system memory.
DDSCAPS_VIDEOMEMORY Indicates that this surface exists in display memory.

/

LPDIRECTDRAWSURFACE7 lpddsprimary = NULL;
DDSURFACEDESC2 ddsd; // the DirectDraw surface description
// MS recommends clearing out the structure
memset(&ddsd,0,sizeof(ddsd)); // could use ZeroMemory()
// now fill in size of structure

ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
// now create the primary surface

if (FAILED(lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL)))
{
// error

} // end if

/


 

8.Attaching the Palette

    HRESULT SetPalette(LPDIRECTDRAWPALETTE lpDDPalette);

if (FAILED(lpddsprimary->SetPalette(lpddpal)))
   {
   // error
   } // end if

9.Plotting Pixels

    All DirectDraw video modes and surfaces are linear.

// assume this points to VRAM or the surface memory
UCHAR *video_buffer8;
video_buffer8[x + y*memory_pitchB] = pixel_color_8;

// assume this points to VRAM or the surface memory
USHORT *video_buffer16;
video_buffer16[x + y*(memory_pitchB >> 1)] = pixel_color_16;

// this builds a 16 bit color value in 5.5.5 format (1-bit alpha mode)
#define _RGB16BIT555(r,g,b) ((b & 31) + ((g & 31) << 5) + ((r & 31) << 10))

// this builds a 16 bit color value in 5.6.5 format (green dominate mode)
#define _RGB16BIT565(r,g,b) ((b & 31) + ((g & 63) << 5) + ((r & 31) << 11))

要访问任何显示表面(主、从)时,必须对内存加锁解锁
HRESULT Lock(LPRECT   lpDestRect,      // destination RECT to lock, NULL to full windows
     LPDDSURFACEDESC2 lpDDSurfaceDesc, // address of struct to receive info
     DWORD            dwFlags,         // request flags
     HANDLE           hEvent);         // advanced, make NULL

DDLOCK_READONLY Indicates that the surface being locked will be read-only.
DDLOCK_SURFACEMEMORYPTR Indicates that a valid memory pointer to the top of the specified RECT should be returned. If no rectangle is specified, a pointer to the top of the surface is returned. This is the default.
DDLOCK_WAIT If a lock cannot be obtained because a blit operation is in progress, the method retries until a lock is obtained or another error occurs, such as DDERR_SURFACEBUSY.
DDLOCK_WRITEONLY Indicates that the surface being locked will be write-enabled.

HRESULT Unlock(LPRECT lpRect);

/

inline void Plot8(int x, int y,  // position of pixel
              UCHAR color,   // color index of pixel
              UCHAR *buffer, // pointer to surface memory
              int mempitch)  // memory pitch per line
{
// this function plots a single pixel
buffer[x+y*mempitch] = color;

} // end Plot8

Plot8(100,20,26, (UCHAR *)ddsd.lpSurface,(int)ddsd.lPitch);

/

Similarly, here's a 16-bit 5.6.5 RGB mode plot function:

inline void Plot16(int x, int y,  // position of pixel
              UCHAR red,
              UCHAR green,
              UCHAR, blue  // RGB color of pixel
              USHORT *buffer, // pointer to surface memory
              int mempitch)   // memory pitch bytes per line
{
// this function plots a single pixel
buffer[x+y*(mempitch>>1)] = __RGB16BIT565(red,green,blue);

} // end Plot16

Plot16(300,100,10,14,30,(USHORT *)ddsd.lpSurface,(int)ddsd.lPitch);

/

10.清理资源

// first kill the palette
if (lpddpal)
   {
   lpddpal->Release();
   lpddpal = NULL;
   } // end if

// now the primary surface
if (lpddsprimary)
    lpddsprimary->Release();


// and finally the directdraw object itself
if (lpdd)
   {
   lpdd->Release();
   lpdd = NULL;

   } // end if

   

 


   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值