DirectDraw API Reference
Complete documentation of all interfaces, methods, structs, flags, and result codes
declared in include/ddraw.h. Based directly on the source code in
src/directdraw/DirectDraw.cpp.
Each entry carries one of: Implemented — works as expected, Partial — works for the common case with documented gaps, Stub — compiles, returns success, performs no real work, Not supported — absent or always errors.
Contents
- Global function — DirectDrawCreate
- IDirectDraw interface
- IDirectDrawSurface interface
- IDirectDrawPalette interface
- IDirectDrawClipper interface
- Structs and types
- Flags reference
- Result codes
- Pointer typedefs
Global function
HRESULT WINAPI DirectDrawCreate(
const GUID* lpGUID,
LPDIRECTDRAW* lplpDD,
IUnknown* pUnkOuter
);
Creates a new DirectDraw device object backed by an SDL3 renderer. This is the entry point for all DirectDraw usage.
Parameters
| Parameter | Type | Direction | Description |
|---|---|---|---|
lpGUID | const GUID* | in | Ignored. In the original API this selects a specific DirectDraw driver (NULL = primary display driver, a specific GUID = a secondary adapter). free-direct always creates one SDL-backed instance regardless of this value. |
lplpDD | LPDIRECTDRAW* | out |
Receives the pointer to the newly created IDirectDraw object.
Must not be NULL. The returned object has an initial reference count of 1.
Caller must call Release() when done.
|
pUnkOuter | IUnknown* | in |
Must be NULL. COM aggregation is not supported. Passing a non-NULL value
returns DDERR_INVALIDPARAMS.
|
Return values
DD_OK | Object created successfully. |
DDERR_INVALIDPARAMS | lplpDD is NULL, or pUnkOuter is non-NULL. |
DDERR_OUTOFMEMORY | Heap allocation for the internal object failed. |
Ownership and lifetime
Caller owns the returned object. Call Release() exactly once when done.
All surfaces, palettes, and clippers created through this object hold their own
references and are independent.
Behavioral difference from original DirectX 3
The original function consults the DirectDraw driver registry and can fail if no display driver is installed. free-direct always succeeds on any SDL3-capable platform.
IDirectDraw interface
Returned by DirectDrawCreate. Provides top-level device operations:
cooperative level, display mode, and object factories for surfaces, palettes, and clippers.
typedef struct IDirectDraw* LPDIRECTDRAW;
ULONG WINAPI AddRef();
Increments the internal reference count by 1. Returns the new count.
Thread-safe: uses std::atomic<ULONG> internally.
ULONG WINAPI Release();
Decrements the reference count by 1 and returns the new count. When the count reaches 0, the object is destroyed:
- The SDL renderer is destroyed (
SDL_DestroyRenderer). - The window is restored from fullscreen via
FreeApiSetWindowFullscreen(false). - The SDL window handle is released (but not destroyed — the window belongs to the caller).
HRESULT WINAPI QueryInterface(const GUID& riid, void** ppvObject);
Always returns DDERR_UNSUPPORTED. COM interface promotion (e.g. to
IDirectDraw2, IDirectDraw4) is not implemented.
HRESULT WINAPI SetCooperativeLevel(HWND hWnd, DWORD dwFlags);
Associates the DirectDraw object with a window, creates the SDL renderer for that window, and optionally requests fullscreen mode. Must be called before any surfaces are created.
Parameters
| Parameter | Type | Direction | Description |
|---|---|---|---|
hWnd | HWND | in |
Handle to the application window. free-api uses SDL windows internally;
the HWND is a reinterpret-cast of SDL_Window*.
Must not be NULL — returns DDERR_INVALIDPARAMS if NULL.
|
dwFlags | DWORD | in | Cooperative level flags. See DDSCL_* flags below. The combination actually determines windowed vs. fullscreen behavior. |
What happens internally
- Stores
hWndand casts it toSDL_Window*. - If
DDSCL_FULLSCREEN: callsFreeApiSetWindowFullscreen(true). - If
DDSCL_NORMAL: callsFreeApiSetWindowFullscreen(false). - Destroys any pre-existing renderer attached to the window (legacy re-init pattern).
- Calls
SDL_CreateRenderer(sdlWindow, NULL)to create a hardware-accelerated renderer. - If the default renderer fails, falls back to
SDL_CreateRenderer(sdlWindow, "software"). - Enables VSync via
SDL_SetRenderVSync(renderer, 1)unlessFREE_DIRECT_ENABLE_VSYNC=0.
Return values
DD_OK | Renderer created successfully. |
DDERR_INVALIDPARAMS | hWnd is NULL. |
DDERR_GENERIC | Both default and software renderer creation failed. |
Limitations vs. original DirectX 3
- Does not acquire exclusive hardware access.
DDSCL_EXCLUSIVEis accepted but provides no additional privilege.- Multiple calls on the same object destroy and recreate the renderer.
HRESULT WINAPI SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP);
Stores the game's logical rendering resolution and requests fullscreen mode. Does not change the physical display resolution.
Parameters
| Parameter | Type | Direction | Description |
|---|---|---|---|
dwWidth | DWORD | in |
Logical width in pixels (e.g. 640). Stored internally as
displayModeWidth_ and used as the primary surface width
when CreateSurface is subsequently called with
DDSCAPS_PRIMARYSURFACE.
|
dwHeight | DWORD | in |
Logical height in pixels (e.g. 480). Stored as displayModeHeight_.
|
dwBPP | DWORD | in |
Bits per pixel requested (e.g. 8, 16, 32). Stored but not used
by the current implementation. Primary surface BPP is always determined by the
DDPIXELFORMAT field in CreateSurface, or defaults to
32-bit when none is provided.
|
Side effect
Calls FreeApiSetWindowFullscreen(hwnd_, true) if a window has already
been associated via SetCooperativeLevel.
SDL3's logical presentation (letterbox scaling) is applied at first present.
Return values
DD_OK | Always returned (values are stored unconditionally). |
HRESULT WINAPI CreateSurface(
const DDSURFACEDESC* lpDDSurfaceDesc,
LPDIRECTDRAWSURFACE* lplpDDSurface,
IUnknown* pUnkOuter
);
Creates a DirectDraw surface object. Allocates a CPU pixel buffer immediately. The exact type and dimensions depend on the descriptor.
Parameters
| Parameter | Type | Direction | Description |
|---|---|---|---|
lpDDSurfaceDesc | const DDSURFACEDESC* | in |
Pointer to a filled DDSURFACEDESC structure.
dwSize must equal sizeof(DDSURFACEDESC).
Must not be NULL.
|
lplpDDSurface | LPDIRECTDRAWSURFACE* | out | Receives the new surface pointer. Must not be NULL. The returned object has an initial reference count of 1. |
pUnkOuter | IUnknown* | in | Must be NULL. Returns DDERR_INVALIDPARAMS if non-NULL. |
Supported surface types (determined by ddsCaps.dwCaps)
| Cap flag | Behavior |
|---|---|
DDSCAPS_PRIMARYSURFACE |
Creates the primary surface. Dimensions: uses displayModeWidth_ ×
displayModeHeight_ if SetDisplayMode was called,
otherwise defaults to 640 × 480. BPP: 32-bit (unless the descriptor sets
DDPF_PALETTEINDEXED8). The descriptor's dwWidth/
dwHeight fields are ignored for the primary surface.
Cannot be combined with any offscreen cap.
|
DDSCAPS_OFFSCREENPLAIN |
Creates an offscreen surface. Requires DDSD_WIDTH | DDSD_HEIGHT
in dwFlags. BPP comes from ddpfPixelFormat.dwRGBBitCount
if DDSD_PIXELFORMAT is set, otherwise defaults to 32.
Only 8 and 32 are accepted; any other value is promoted to 32.
|
DDSCAPS_SYSTEMMEMORY |
Treated identically to DDSCAPS_OFFSCREENPLAIN.
Used by legacy code to explicitly request a CPU-side surface.
|
Return values
DD_OK | Surface created. |
DDERR_INVALIDPARAMS | NULL pointer, wrong dwSize, invalid cap combination, or missing width/height for offscreen. |
DDERR_OUTOFMEMORY | Pixel buffer allocation failed. |
Pixel buffer layout after creation
- 8-bit:
width × heightbytes, one byte per pixel = palette index. - 32-bit:
width × height × 4bytes, four bytes per pixel in R,G,B,A order. - All pixels initialized to 0.
HRESULT WINAPI CreatePalette(
DWORD dwFlags,
LPPALETTEENTRY lpColorTable,
LPDIRECTDRAWPALETTE* lplpDDPalette,
IUnknown* pUnkOuter
);
Creates a palette object holding up to 256 color entries.
Parameters
| Parameter | Type | Direction | Description |
|---|---|---|---|
dwFlags | DWORD | in |
Capability flags. DDPCAPS_8BIT (0x4) is the expected value for
256-entry 8-bit palettes. The flag is stored but not further interpreted;
all palettes are always 256 entries.
|
lpColorTable | LPPALETTEENTRY | in |
Pointer to an array of 256 PALETTEENTRY values.
If NULL, all 256 entries are initialized to {0,0,0,0} (black, opaque).
|
lplpDDPalette | LPDIRECTDRAWPALETTE* | out | Receives the new palette pointer. Must not be NULL. Initial reference count is 1. |
pUnkOuter | IUnknown* | in | Must be NULL. |
Return values
DD_OK | Palette created. |
DDERR_INVALIDPARAMS | lplpDDPalette is NULL or pUnkOuter is non-NULL. |
DDERR_OUTOFMEMORY | Allocation failed. |
HRESULT WINAPI CreateClipper(
DWORD dwFlags,
LPDIRECTDRAWCLIPPER* lplpDDClipper,
IUnknown* pUnkOuter
);
Creates a clipper object. In free-direct the clipper's main function is to
signal that a surface is operating in windowed mode, enabling automatic
screen-to-client coordinate translation during Blt calls on the primary surface.
Parameters
| Parameter | Type | Direction | Description |
|---|---|---|---|
dwFlags | DWORD | in | Ignored. Pass 0. |
lplpDDClipper | LPDIRECTDRAWCLIPPER* | out | Receives the new clipper pointer. Initial reference count is 1. |
pUnkOuter | IUnknown* | in | Must be NULL. |
Return values
DD_OK | Clipper created. |
DDERR_INVALIDPARAMS | lplpDDClipper is NULL or pUnkOuter non-NULL. |
DDERR_OUTOFMEMORY | Allocation failed. |
IDirectDrawSurface interface
The main rendering surface. Obtained via IDirectDraw::CreateSurface.
Represents either the primary surface (what is displayed) or an offscreen surface
(used as a back buffer, sprite sheet, or scratch space).
typedef struct IDirectDrawSurface* LPDIRECTDRAWSURFACE;
ULONG WINAPI AddRef();
ULONG WINAPI Release();
Standard reference counting. When Release() reaches 0:
- The SDL texture (if any) is destroyed via
SDL_DestroyTexture. - The attached palette (if any) has its reference released.
- The attached clipper (if any) has its reference released.
- Any attached DC is destroyed via
FreeApiDestroySurfaceDC. - The CPU pixel buffer (
std::vector<uint8_t>) is freed.
HRESULT WINAPI QueryInterface(const GUID& riid, void** ppvObject);
Always returns DDERR_UNSUPPORTED. Interface promotion not implemented.
HRESULT WINAPI Blt(
LPRECT lpDestRect,
LPDIRECTDRAWSURFACE lpDDSrcSurface,
LPRECT lpSrcRect,
DWORD dwFlags,
LPDDBLTFX lpDDBltFx
);
General-purpose blit. Operates entirely in CPU memory. Two modes are supported:
color fill (when DDBLT_COLORFILL is set) and surface-to-surface copy
(when lpDDSrcSurface is non-NULL).
Parameters
| Parameter | Type | Direction | Description |
|---|---|---|---|
lpDestRect | LPRECT | in |
Destination rectangle on this surface. If NULL, the entire surface is
the destination. Coordinates are clamped to surface bounds.
Windowed coordinate adjustment: when this surface is the primary surface and has a clipper attached, the rectangle is adjusted from screen coordinates to window-local coordinates by subtracting the SDL window position ( SDL_GetWindowPosition). This compensates for legacy game
code that converts client coords to screen coords before blitting.
|
lpDDSrcSurface | LPDIRECTDRAWSURFACE | in |
Source surface for surface-to-surface copy. Pass NULL when using
DDBLT_COLORFILL.
|
lpSrcRect | LPRECT | in |
Source rectangle on lpDDSrcSurface. If NULL, the entire source
surface is used. Coordinates are clamped to source surface bounds.
|
dwFlags | DWORD | in |
Bitmask of DDBLT_* flags controlling the blit mode.
The most important flags are:
|
lpDDBltFx | LPDDBLTFX | in |
Pointer to a DDBLTFX structure providing effect parameters.
Required when DDBLT_COLORFILL is set (returns
DDERR_INVALIDPARAMS if NULL in that case).
Ignored for plain surface-to-surface blits.
|
Color fill mode (DDBLT_COLORFILL)
Fills the destination rectangle with a solid color from lpDDBltFx->dwFillColor:
- 32-bit surfaces:
dwFillColor=0x00RRGGBB. Alpha byte is set to 255 (opaque). - 8-bit surfaces: the low byte of
dwFillColoris used as the palette index. The color key value 0 makes index 0 transparent in subsequent blits.
Surface-to-surface copy
Copies pixels from the source surface rectangle to the destination rectangle:
- Nearest-neighbor scaling when source and destination rectangles have different sizes.
- Only 8→8 and 32→32 bit depth combinations are handled. Mixed depths (8→32 or 32→8) skip all pixels silently.
- Source color key is applied when
DDBLT_KEYSRCis set and the source has a color key (seeSetColorKey).
Auto-present behavior
If the destination is the primary surface, owner->renderer_ is
non-NULL, and Flip() has never been called on the owning
IDirectDraw instance, PresentPrimary is called
automatically after a successful blit. This supports the Speedy Blupi pattern
of blitting directly to the primary without a separate Flip call.
Return values
DD_OK | Blit completed (or fill completed). |
DDERR_INVALIDPARAMS | COLORFILL without DDBLTFX, or source surface type mismatch. |
DDERR_UNSUPPORTED | Unsupported flag combination (no source, no fill). |
HRESULT WINAPI BltFast(
DWORD dwX,
DWORD dwY,
LPDIRECTDRAWSURFACE lpDDSrcSurface,
LPRECT lpSrcRect,
DWORD dwTrans
);
Fast surface-to-surface copy without scaling. Copies the source rectangle to
position (dwX, dwY) on this surface. The destination rectangle is
always the same size as the source rectangle.
Parameters
| Parameter | Type | Direction | Description |
|---|---|---|---|
dwX | DWORD | in | X coordinate of the top-left corner of the destination on this surface. |
dwY | DWORD | in | Y coordinate of the top-left corner of the destination on this surface. |
lpDDSrcSurface | LPDIRECTDRAWSURFACE | in | Source surface. Must not be NULL; returns DDERR_INVALIDPARAMS if NULL. |
lpSrcRect | LPRECT | in |
Source rectangle. If NULL, the entire source surface is copied.
The destination area is computed as
(dwX, dwY, dwX + srcWidth, dwY + srcHeight).
|
dwTrans | DWORD | in |
Transparency flags. See DDBLTFAST_*:
|
Return values
DD_OK | Copy completed. |
DDERR_INVALIDPARAMS | lpDDSrcSurface is NULL or type mismatch. |
Auto-present behavior is the same as Blt.
HRESULT WINAPI Flip(
LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride,
DWORD dwFlags
);
Presents the primary surface to the screen by uploading the CPU pixel buffer
to SDL and calling SDL_RenderPresent.
This is not a real DirectDraw page flip.
There is no flip chain; only the primary surface's CPU buffer is presented.
Parameters
| Parameter | Type | Direction | Description |
|---|---|---|---|
lpDDSurfaceTargetOverride | LPDIRECTDRAWSURFACE | in | Ignored. In the original API this selects a specific surface from a flip chain. |
dwFlags | DWORD | in | Ignored. In the original API controls flip timing (DDFLIP_WAIT etc.). |
Effect of calling Flip
After the first call to Flip():
owner_->usesFlip_is set to true.- Auto-present from
Blt/BltFastis disabled. Flip()becomes the only way to update the screen.
Presentation pipeline (called internally)
- Frame throttle: if called within the frame interval (default 1000 ms / 60 = 16.67 ms) since the last present, returns
DD_OKimmediately. - Dirty check: if the primary surface pixel buffer has not been written since the last present, skips upload and present.
- Palette expansion (8-bit only): expands all pixel indices to RGBA32 using the attached palette (or a default 3:3:2 palette if none is attached). Uses a cached
paletteConvertBuffer_to avoid per-frame heap allocation. - Texture upload:
SDL_UpdateTextureuploads the pixel data to a cached streamingSDL_Texture(RGBA32, STREAMING access). - Render clear:
SDL_RenderClearwith black. - Logical presentation (once):
SDL_SetRenderLogicalPresentation(renderer, W, H, SDL_LOGICAL_PRESENTATION_LETTERBOX)is called on the first present to set up letterbox scaling. - Render:
SDL_RenderTexture(renderer, texture, NULL, NULL). - Present:
SDL_RenderPresentexactly once.
Return values
DD_OK | Present complete (or skipped due to throttle/dirty check). |
DDERR_UNSUPPORTED | Called on a non-primary surface, or no renderer available. |
DDERR_GENERIC | SDL texture creation failed. |
HRESULT WINAPI Lock(
LPRECT lpDestRect,
LPDDSURFACEDESC lpDDSurfaceDesc,
DWORD dwFlags,
HANDLE hEvent
);
Provides direct CPU access to the surface's pixel buffer.
Returns a pointer to the pixel data via lpDDSurfaceDesc->lpSurface.
The lock is always immediately available — there is no GPU synchronization.
Parameters
| Parameter | Type | Direction | Description |
|---|---|---|---|
lpDestRect | LPRECT | in |
Accepted but ignored. In the original API, a partial lock
returns a pointer offset into the buffer. free-direct always returns a pointer
to the full buffer beginning regardless of lpDestRect.
|
lpDDSurfaceDesc | LPDDSURFACEDESC | in/out |
Caller must fill dwSize = sizeof(DDSURFACEDESC) before calling.
On success, the following fields are filled:
|
dwFlags | DWORD | in |
Ignored. In the original API: DDLOCK_WAIT,
DDLOCK_READONLY, DDLOCK_WRITEONLY.
free-direct always returns the buffer immediately.
|
hEvent | HANDLE | in | Ignored. Pass NULL. |
Return values
DD_OK | Lock successful; lpDDSurfaceDesc->lpSurface is valid. |
DDERR_INVALIDPARAMS | lpDDSurfaceDesc is NULL or dwSize is wrong. |
Writing to the pixel buffer via the lpSurface pointer does not
automatically mark the primary surface dirty. After modifying pixels directly,
call a blit method (even a no-op blit) to trigger the dirty flag, or the changes
may not appear until the next frame that is dirty for another reason.
HRESULT WINAPI Unlock(LPVOID lpSurfaceData);
No-op. Always returns DD_OK. The lpSurfaceData parameter is
ignored. There is no hardware lock to release and the pixel buffer pointer remains valid.
HRESULT WINAPI GetSurfaceDesc(LPDDSURFACEDESC lpDDSurfaceDesc);
Fills a DDSURFACEDESC with the current surface properties.
Caller must set dwSize = sizeof(DDSURFACEDESC) before calling.
Returns the same information as Lock but without providing a pixel pointer
for primary surfaces.
Parameters
| Parameter | Type | Direction | Description |
|---|---|---|---|
lpDDSurfaceDesc | LPDDSURFACEDESC | out |
Must not be NULL. Must have dwSize = sizeof(DDSURFACEDESC).
Fields filled: dwFlags, dwWidth, dwHeight,
ddsCaps, ddpfPixelFormat.
For offscreen surfaces: also lPitch and lpSurface.
|
Return values
DD_OK | Descriptor filled. |
DDERR_INVALIDPARAMS | NULL pointer or wrong dwSize. |
HRESULT WINAPI SetColorKey(DWORD dwFlags, LPDDCOLORKEY lpDDColorKey);
Sets the color key for transparent blits from this surface. Only source blit color keys are supported.
Parameters
| Parameter | Type | Direction | Description |
|---|---|---|---|
dwFlags | DWORD | in |
Must be DDCKEY_SRCBLT (0x8). Any other value returns
DDERR_UNSUPPORTED. Destination color keys and overlay color
keys are not implemented.
|
lpDDColorKey | LPDDCOLORKEY | in | Pointer to a DDCOLORKEY structure defining the transparent range. If NULL, clears the color key (disables transparency). |
Color key comparison semantics
| Surface BPP | Comparison |
|---|---|
| 8-bit |
The palette index byte is compared against
dwColorSpaceLowValue and dwColorSpaceHighValue.
Pixel is transparent if index >= low && index <= high.
|
| 32-bit |
Two comparisons are performed:
|
Return values
DD_OK | Color key stored. |
DDERR_UNSUPPORTED | dwFlags is not DDCKEY_SRCBLT. |
HRESULT WINAPI SetPalette(LPDIRECTDRAWPALETTE lpDDPalette);
Associates a palette with this surface. Reference-counted.
Parameters
| Parameter | Type | Direction | Description |
|---|---|---|---|
lpDDPalette | LPDIRECTDRAWPALETTE | in |
The palette to attach. If non-NULL, AddRef() is called on it.
The previous palette (if any) has Release() called.
Pass NULL to detach the current palette.
|
Effect
- On an 8-bit primary surface: the palette is used during
PresentPrimaryto expand indices to RGBA32. If no palette is set, a default 3:3:2 palette is used. - On an 8-bit offscreen surface: the palette is used during
GetDC(expansion to RGBA32) andReleaseDC(nearest-match quantization). - On 32-bit surfaces: the palette is stored but has no effect on rendering.
Return values
DD_OK | Always returned. |
HRESULT WINAPI SetClipper(LPDIRECTDRAWCLIPPER lpDDClipper);
Associates a clipper with this surface. Reference-counted.
Parameters
| Parameter | Type | Direction | Description |
|---|---|---|---|
lpDDClipper | LPDIRECTDRAWCLIPPER | in |
Clipper to attach. If non-NULL, AddRef() is called.
Previous clipper is released. Pass NULL to detach.
|
Effect
The presence of a clipper on the primary surface activates windowed-mode
coordinate adjustment in Blt: destination rectangles expressed
in screen coordinates are translated to window-local coordinates by subtracting
the SDL window's position.
Return values
DD_OK | Always returned. |
HRESULT WINAPI IsLost();
Always returns DD_OK (not lost).
Surfaces in free-direct are CPU-resident and never lose their content.
Legacy game code that polls IsLost() in a loop will not spin.
HRESULT WINAPI Restore();
Always returns DD_OK. No restoration is needed.
HRESULT WINAPI GetDC(HDC* lphDC);
Returns a GDI-compatible device context backed by the surface's pixel buffer.
Needed by the DDColorMatch pattern: GetDC → SetPixel
→ Lock → read index back → Unlock → ReleaseDC.
Parameters
| Parameter | Type | Direction | Description |
|---|---|---|---|
lphDC | HDC* | out | Receives the HDC. Must not be NULL. |
Behavior by surface format
| Format | Behavior |
|---|---|
| 32-bit |
DC is created directly over the CPU pixel buffer via
FreeApiCreateSurfaceDC(pixels, w, h, pitch, 32).
Modifications are immediately visible in the pixel buffer.
|
| 8-bit |
A temporary 32-bit RGBA buffer is allocated (dcTempBuffer_).
The 256 palette entries are read, then each pixel index is expanded to RGBA.
The DC is created over this temporary buffer.
See ReleaseDC for how changes are written back.
|
Return values
DD_OK | DC returned in *lphDC. |
DDERR_INVALIDPARAMS | lphDC is NULL. |
DDERR_UNSUPPORTED | Pixel buffer is empty. |
DDERR_GENERIC | DC creation via free-api failed. |
HRESULT WINAPI ReleaseDC(HDC hDC);
Releases the device context returned by GetDC.
For 8-bit surfaces, converts the modified temporary RGBA buffer back to palette
indices using nearest-match squared-RGB distance for each pixel, then frees the
temporary buffer.
Destroys the DC so a fresh one is created on the next GetDC call.
Parameters
| Parameter | Type | Direction | Description |
|---|---|---|---|
hDC | HDC | in | Must be the HDC returned by the most recent GetDC on this surface.
Returns DDERR_INVALIDPARAMS if it does not match. |
Return values
DD_OK | DC released. |
DDERR_INVALIDPARAMS | DC does not match the surface's attached DC. |
IDirectDrawPalette interface
Holds a table of up to 256 PALETTEENTRY values.
Obtained via IDirectDraw::CreatePalette and attached to surfaces via
IDirectDrawSurface::SetPalette.
typedef struct IDirectDrawPalette* LPDIRECTDRAWPALETTE;
ULONG WINAPI AddRef();
ULONG WINAPI Release();
Standard reference counting. Release() to 0 frees the palette's
256-entry internal array.
HRESULT WINAPI GetEntries(
DWORD dwFlags,
DWORD dwBase,
DWORD dwNumEntries,
LPPALETTEENTRY lpEntries
);
Reads a contiguous range of palette entries into the caller-provided array.
Parameters
| Parameter | Type | Direction | Description |
|---|---|---|---|
dwFlags | DWORD | in | Ignored. Pass 0. |
dwBase | DWORD | in | Index of the first entry to read (0–255). |
dwNumEntries | DWORD | in | Number of entries to read. dwBase + dwNumEntries must be ≤ 256. |
lpEntries | LPPALETTEENTRY | out | Caller-allocated array of at least dwNumEntries PALETTEENTRY structures. |
Return values
DD_OK | Entries copied. |
DDERR_INVALIDPARAMS | lpEntries is NULL or range out of bounds. |
HRESULT WINAPI SetEntries(
DWORD dwFlags,
DWORD dwBase,
DWORD dwNumEntries,
LPPALETTEENTRY lpEntries
);
Writes a contiguous range of palette entries from the caller-provided array.
Parameters
| Parameter | Type | Direction | Description |
|---|---|---|---|
dwFlags | DWORD | in | Ignored. Pass 0. |
dwBase | DWORD | in | Index of the first entry to write (0–255). |
dwNumEntries | DWORD | in | Number of entries to write. dwBase + dwNumEntries must be ≤ 256. |
lpEntries | LPPALETTEENTRY | in | Array of dwNumEntries entries to copy into the palette. |
Return values
DD_OK | Entries written. |
DDERR_INVALIDPARAMS | lpEntries is NULL or range out of bounds. |
IDirectDrawClipper interface
Used in windowed mode to signal that blits to the primary surface should translate
screen coordinates to window-local coordinates. Obtained via
IDirectDraw::CreateClipper.
typedef struct IDirectDrawClipper* LPDIRECTDRAWCLIPPER;
ULONG WINAPI AddRef();
ULONG WINAPI Release();
Standard reference counting. Release() to 0 frees the clipper object.
HRESULT WINAPI SetHWnd(DWORD dwFlags, HWND hWnd);
Stores the HWND associated with this clipper.
Parameters
| Parameter | Type | Direction | Description |
|---|---|---|---|
dwFlags | DWORD | in | Ignored. Pass 0. |
hWnd | HWND | in |
The window handle to associate. Stored internally as hwnd_.
Not actively used for clip region management — only its presence on a surface
matters for coordinate translation.
|
Return values
DD_OK | Always returned. |
Limitation vs. original DirectX 3
In original DirectDraw, the clipper maintains a clip list (RGNDATA) based on the visible region of the HWND. free-direct does not maintain clip regions; it only uses the window position for coordinate translation.
Structs and types
DDSURFACEDESC
typedef struct _DDSURFACEDESC {
DWORD dwSize; // [in] Must be sizeof(DDSURFACEDESC)
DWORD dwFlags; // [in] Bitmask of DDSD_* flags indicating which fields are valid
DWORD dwHeight; // [in/out] Surface height in pixels
DWORD dwWidth; // [in/out] Surface width in pixels
union {
LONG lPitch; // [out] Bytes per scan line (stride)
DWORD dwLinearSize; // Not used by free-direct
};
DWORD dwBackBufferCount; // Not used by free-direct
union {
DWORD dwMipMapCount; // Not used
DWORD dwZBufferBitDepth; // Not used
DWORD dwRefreshRate; // Not used
};
DWORD dwAlphaBitDepth; // Not used
DWORD dwReserved; // Reserved, always 0
LPVOID lpSurface; // [out] Pointer to pixel buffer (set by Lock/GetSurfaceDesc)
DDCOLORKEY ddckCKDestOverlay; // Not used by free-direct
DDCOLORKEY ddckCKDestBlt; // Not used by free-direct
DDCOLORKEY ddckCKSrcOverlay; // Not used by free-direct
DDCOLORKEY ddckCKSrcBlt; // Not used by free-direct
DDPIXELFORMAT ddpfPixelFormat; // [in] Pixel format for CreateSurface; [out] in Lock/GetSurfaceDesc
DDSCAPS ddsCaps; // [in] Surface capability flags (DDSCAPS_*)
} DDSURFACEDESC, *LPDDSURFACEDESC;
Used as input to CreateSurface and as output from Lock and GetSurfaceDesc.
Field notes
| Field | Usage context | Notes |
|---|---|---|
dwSize | All calls | Must equal sizeof(DDSURFACEDESC) or the call fails. |
dwFlags | CreateSurface (in) | Bitmask of DDSD_* flags indicating which other fields contain valid input. |
dwHeight | CreateSurface (in), Lock/GetSurfaceDesc (out) | Surface height in pixels. Required for offscreen surfaces (DDSD_HEIGHT must be set). |
dwWidth | CreateSurface (in), Lock/GetSurfaceDesc (out) | Surface width in pixels. Required for offscreen surfaces (DDSD_WIDTH must be set). |
lPitch | Lock/GetSurfaceDesc (out) | Bytes per row = width × (bpp / 8). Use this value (not width × 4) to step between rows when accessing lpSurface. |
lpSurface | Lock/GetSurfaceDesc (out) | Direct pointer into the std::vector<uint8_t>. Valid until the surface is destroyed. For primary surfaces, only set by Lock, not by GetSurfaceDesc. |
ddpfPixelFormat | CreateSurface (in), Lock/GetSurfaceDesc (out) | Pixel format description. Required with DDSD_PIXELFORMAT flag to select 8-bit vs 32-bit in CreateSurface. |
ddsCaps | CreateSurface (in), GetSurfaceDesc (out) | Capability flags. The dwCaps member selects the surface type. |
DDPIXELFORMAT
typedef struct _DDPIXELFORMAT {
DWORD dwSize; // [in] Must be sizeof(DDPIXELFORMAT)
DWORD dwFlags; // [in/out] DDPF_* flags
DWORD dwFourCC; // Not used by free-direct
union {
DWORD dwRGBBitCount; // Bits per pixel (8 or 32)
DWORD dwYUVBitCount; // Not used
DWORD dwZBufferBitDepth; // Not used
DWORD dwAlphaBitDepth; // Not used
};
union {
DWORD dwRBitMask; // [out] 0x00FF0000 for 32-bit RGB
DWORD dwYBitMask; // Not used
};
union {
DWORD dwGBitMask; // [out] 0x0000FF00 for 32-bit RGB
DWORD dwUBitMask; // Not used
};
union {
DWORD dwBBitMask; // [out] 0x000000FF for 32-bit RGB
DWORD dwVBitMask; // Not used
};
union {
DWORD dwRGBAlphaBitMask; // Not used (alpha is always 0xFF internally)
DWORD dwYUVAlphaBitMask; // Not used
};
} DDPIXELFORMAT, *LPDDPIXELFORMAT;
Values written by GetSurfaceDesc / Lock
| Surface type | dwFlags | dwRGBBitCount | dwRBitMask / G / B |
|---|---|---|---|
| 8-bit paletted | DDPF_PALETTEINDEXED8 (0x20) |
8 | 0 / 0 / 0 (no RGB masks for indexed) |
| 32-bit RGB | DDPF_RGB (0x40) |
32 | 0x00FF0000 / 0x0000FF00 / 0x000000FF |
DDCOLORKEY
typedef struct _DDCOLORKEY {
DWORD dwColorSpaceLowValue; // Low end of the transparent color range (inclusive)
DWORD dwColorSpaceHighValue; // High end of the transparent color range (inclusive)
} DDCOLORKEY, *LPDDCOLORKEY;
Defines a range of pixel values to be treated as transparent in blits.
Pixel p is transparent if dwColorSpaceLowValue <= p <= dwColorSpaceHighValue.
For a single-color key (the most common case), set both fields to the same value.
Example for magenta on a 32-bit surface: {0x00FF00FF, 0x00FF00FF}.
Example for palette index 0 on an 8-bit surface: {0, 0}.
DDSCAPS
typedef struct _DDSCAPS {
DWORD dwCaps; // Bitmask of DDSCAPS_* flags
} DDSCAPS, *LPDDSCAPS;
Simple wrapper around a capability bitmask. Used in DDSURFACEDESC.ddsCaps.
DDBLTFX
typedef struct _DDBLTFX {
DWORD dwSize; // [in] Must be sizeof(DDBLTFX)
DWORD dwDDFX; // Not used by free-direct
DWORD dwROP; // Not used by free-direct
DWORD dwDDROP; // Not used by free-direct
DWORD dwRotationAngle; // Accepted but rotation NOT performed
DWORD dwZBufferDestConst; // Not used
DWORD dwZBufferDestOverlap;// Not used
DWORD dwZBufferSrcConst; // Not used
DWORD dwZBufferSrcOverlap; // Not used
DWORD dwYCbCrDestConst; // Not used
DWORD dwYCbCrSrcConst; // Not used
DWORD dwAlphaDestConst; // Not used
DWORD dwAlphaSrcConst; // Not used
DWORD dwFillColor; // [in] Fill color for DDBLT_COLORFILL
DDCOLORKEY ddckDestColorkey; // Not used
DDCOLORKEY ddckSrcColorkey; // Not used (color key is stored on the surface, not here)
} DDBLTFX, *LPDDBLTFX;
Field notes
| Field | Notes |
|---|---|
dwSize |
Must equal sizeof(DDBLTFX). |
dwFillColor |
Used only when DDBLT_COLORFILL is set in Blt.32-bit surfaces: interpreted as 0x00RRGGBB.
The alpha byte is forced to 255.8-bit surfaces: the low byte (bits 0–7) is used as the palette index. |
dwRotationAngle |
Accepted in the struct (can be set without error) but the rotation is never applied. The blit proceeds as a standard copy. |
PALETTEENTRY
typedef struct tagPALETTEENTRY {
BYTE peRed; // Red component (0–255)
BYTE peGreen; // Green component (0–255)
BYTE peBlue; // Blue component (0–255)
BYTE peFlags; // Flags (ignored by free-direct; pass 0)
} PALETTEENTRY, *PPALETTEENTRY, *LPPALETTEENTRY;
One entry in a 256-color palette. peFlags is accepted but ignored.
Used in arrays of 256 entries with CreatePalette, GetEntries,
and SetEntries.
Flags reference
DDSCAPS_* surface capability flags
| Constant | Value | Support | Description |
|---|---|---|---|
DDSCAPS_PRIMARYSURFACE | 0x00000200 | Implemented | Primary (displayed) surface. Size comes from SetDisplayMode or defaults to 640×480. |
DDSCAPS_OFFSCREENPLAIN | 0x00000040 | Implemented | Plain offscreen surface in system memory. Width and height required. |
DDSCAPS_SYSTEMMEMORY | 0x00000800 | Implemented | Explicitly system-memory surface. Treated identically to OFFSCREENPLAIN. |
DDSD_* surface description flags
| Constant | Value | Description |
|---|---|---|
DDSD_CAPS | 0x00000001 | Indicates ddsCaps is valid. Always required for CreateSurface. |
DDSD_HEIGHT | 0x00000002 | Indicates dwHeight is valid. Required for offscreen surfaces. |
DDSD_WIDTH | 0x00000004 | Indicates dwWidth is valid. Required for offscreen surfaces. |
DDSD_PITCH | 0x00000008 | Indicates lPitch is valid. Set in the output of Lock/GetSurfaceDesc for offscreen surfaces. |
DDSD_LPSURFACE | 0x00000800 | Indicates lpSurface is valid. Set in the output of Lock/GetSurfaceDesc for offscreen surfaces. |
DDSD_PIXELFORMAT | 0x00001000 | Indicates ddpfPixelFormat is valid. Set this in CreateSurface to specify 8-bit or 32-bit format explicitly. |
DDBLT_* blit flags (used with Blt)
| Constant | Value | Support | Description |
|---|---|---|---|
DDBLT_COLORFILL | 0x00000400 | Implemented | Fill the destination rectangle with DDBLTFX.dwFillColor. Source surface must be NULL. |
DDBLT_KEYSRC | 0x00008000 | Implemented | Apply the source surface's color key. Transparent pixels are not copied to the destination. |
DDBLT_WAIT | 0x00000010 | Stub | Accepted; no-op. Original meaning: wait until hardware is ready rather than returning DDERR_WASSTILLDRAWING. |
DDBLT_ROTATIONANGLE | 0x01000000 | Not supported | Accepted in the flags bitmask (does not cause an error). Rotation angle from DDBLTFX.dwRotationAngle is received but not applied. The blit proceeds without rotation. |
DDBLTFAST_* fast-blit transparency flags (used with BltFast)
| Constant | Value | Support | Description |
|---|---|---|---|
DDBLTFAST_NOCOLORKEY | 0x00000000 | Implemented | Copy all pixels including those matching the color key. This is the default (value 0). |
DDBLTFAST_SRCCOLORKEY | 0x00000001 | Implemented | Skip pixels that match the source surface's color key range. |
DDCKEY_* color key type flags (used with SetColorKey)
| Constant | Value | Support | Description |
|---|---|---|---|
DDCKEY_SRCBLT | 0x00000008 | Implemented | Set the source blit color key. Used to define which pixel values are transparent when this surface is blitted onto another. |
All other DDCKEY_* values (DDCKEY_DESTBLT, DDCKEY_SRCOVERLAY, DDCKEY_DESTOVERLAY) return DDERR_UNSUPPORTED.
DDSCL_* cooperative level flags (used with SetCooperativeLevel)
| Constant | Value | Support | Description |
|---|---|---|---|
DDSCL_FULLSCREEN | 0x00000001 | Partial | Request fullscreen mode. Calls FreeApiSetWindowFullscreen(true). Actual fullscreen depends on the free-api and SDL3 window support. |
DDSCL_EXCLUSIVE | 0x00000010 | Partial | Accepted. In combination with DDSCL_FULLSCREEN indicates exclusive fullscreen. No additional effect in free-direct. |
DDSCL_NORMAL | 0x00000008 | Implemented | Windowed (normal) mode. Calls FreeApiSetWindowFullscreen(false). |
DDPCAPS_* palette capability flags (used with CreatePalette)
| Constant | Value | Support | Description |
|---|---|---|---|
DDPCAPS_8BIT | 0x00000004 | Implemented | 256-entry palette for 8-bit paletted surfaces. Always accepted; all palettes are 256 entries regardless. |
DDPF_* pixel format flags (used in DDPIXELFORMAT.dwFlags)
| Constant | Value | Support | Description |
|---|---|---|---|
DDPF_RGB | 0x00000040 | Implemented | Surface contains raw RGB data. Use with dwRGBBitCount = 32 for 32-bit RGBA surfaces. |
DDPF_PALETTEINDEXED8 | 0x00000020 | Implemented | Surface uses 8-bit palette indices. Each byte is an index into a 256-entry PALETTEENTRY table. |
Result codes
Actively returned by the implementation
| Constant | Value | Meaning |
|---|---|---|
DD_OK | 0x00000000 | Success. |
DDERR_GENERIC | 0x88760000 | Unspecified failure (e.g. SDL renderer creation failed, SDL texture creation failed). |
DDERR_INVALIDPARAMS | 0x88760064 | A required parameter was NULL, out of range, or had a wrong size field. |
DDERR_OUTOFMEMORY | 0x8876017C | Heap allocation failed (new returned nullptr). |
DDERR_UNSUPPORTED | 0x88760032 | QueryInterface, unsupported DDCKEY flags, or unsupported Blt flag combination. |
Defined for compile compatibility, not actively returned
All other DDERR_* constants (DDERR_ALREADYINITIALIZED,
DDERR_SURFACELOST, DDERR_NOCOLORKEY, etc.) are defined in
ddraw.h with unique HRESULT values so that game code that references them
compiles without modification. The implementation does not return them.
Use the SUCCEEDED(hr) and FAILED(hr) macros to check results:
#define SUCCEEDED(hr) (((HRESULT)(hr)) >= 0)
#define FAILED(hr) (((HRESULT)(hr)) < 0)
Pointer typedefs
typedef struct IDirectDraw* LPDIRECTDRAW;
typedef struct IDirectDrawSurface* LPDIRECTDRAWSURFACE;
typedef struct IDirectDrawPalette* LPDIRECTDRAWPALETTE;
typedef struct IDirectDrawClipper* LPDIRECTDRAWCLIPPER;
These are plain pointer typedefs matching the legacy DirectX convention. They are compatible with the concrete implementation classes used internally (since the public interface classes are pure virtual bases).