************************ *** *** *** *** *** DirectDraw Notes *** *** *** *** *** ************************ Last updated September 10, 1996 Notes for DirectDraw 3.0 ======================================== The CoCreateInstance API cannot be used to create an IDirectDraw2 object. To work around this problem, create a DirectDraw object and call QueryInterface on it to get the IDirectDraw2 interface. IDirectDrawSurface2::Flip may cause your machine to hang. To work around this problem, call IDirectDrawSurface::Flip instead. Notes for DirectDraw 2.0 ======================================== In some hardware configurations, stretched transparent blits do not work correctly. If at all possible, when writing DirectDraw applications, you should avoid using stretched transparent blits. To work around this limitation, you can do a stretched blit to an intermediate surface, followed by a transparent blit to your original destination surface. On some, relatively rare, older video boards, source color key blitting to the primary surface may not work. You can work around this by composing your image with transparency to a back buffer, then blitting the result to the primary surface. DirectDraw::Initialize() is now called if the DirectDraw object is created with standard COM methods. Notes for DirectDraw 2.0 Beta 3 ======================================== SetDisplayMode now supports setting the monitor refresh rate ------------------------------------------------------------ The IDirectDraw2::SetDisplayMode function now takes two additional parameters. The dwRefreshRate parameter can be used to specify a monitor refresh rate in Hz. Valid refresh rates can now be enumerated with the IDirectDraw2::EnumDisplayModes function. The refresh rate is returned in the dwRefreshRate field of the DDSURFACEDESC structure. If a refresh rate of 0 is specified in SetDisplayMode, this means to revert back to the IDirectDraw behaviour and set the default refresh rate for the specified mode. The display driver may or may not enumerate specific refresh rates for each mode. If no refresh rate is specified by the driver for a particular mode, the dwRefreshRate field in the DDSURFACEDESC structure set by EnumDisplayModes will be 0. Direct Draw modes now respect monitor settings ---------------------------------------------- Windows 95 allows a user to specify the type of monitor that is being used. DirectDraw now checks the display modes that it knows about against the display restrictions of the installed monitor. If it is determined that the requested mode is not compatible with the monitor, then SetDisplayMode will fail. Only modes which are supported on the installed monitor will be enumerated in EnumDisplayModes. IDirectDrawSurface2::DDGetInterface now supported ------------------------------------------------- A new method has been added to the IDirectDrawSurface2 interface which is call DDGetInterface. This function returns a pointer to the DirectDraw object that was used to create the specified surface. Direct Draw clipper objects now have a COM class factory -------------------------------------------------------- Direct Draw clipper objects now have full class factory support for COM compliance. Clippers can now be created using either CoGetClassObject to obtain a class factory and then calling CreateInstance or by calling CoCreateInstance directly. The class identifier for the clipper class is CLSID_DirectDrawClipper. Please note that it is still possible to create clipper objects using either of the two existing API functions; DirectDrawCreateClipper or IDirectDraw::CreateClipper. Class factory support is provided in addition to these functions rather than in replacement of them. Clippers created by the class factory mechanism must be initialized with the IDirectDrawClipper::Initialize member before use. Initialize takes two parameters; a DirectDraw driver object interface pointer and a flags field. Currently the flags field must be 0. If a NULL driver object is specified then the clipper is not owned by a Direct Draw driver object and behaves identically to clippers created with DirectDrawCreateClipper. If a driver object is specified the clipper will be owned by that driver object and behaves identically to IDirectDraw::CreateClipper. Flip now flips all levels of a mip-map -------------------------------------- Previously, Flip only flipped the the mip-map level supplied as an argument. Now, however, Flip will flip all the levels of a mip-map from the level supplied to the lowest level in the map. A destination surface can also be provided in which case all levels in the mip-map will flip to the back buffer in thier flippable chain which matches the supplied override. For example, if the third back buffer in the top level flippable chain is supplied all levels in the mip-map will flip to thier third back buffer. The number of levels in a mip-map is now stored explicitly ---------------------------------------------------------- The number of levels in a mip-map chain is now stored explicitly. When the surface description of a mip-map is obtained (via IDirectDrawSurface::Lock or IDirectDrawSurface::GetSurfaceDesc) the dwMipMapCount field will contain the number of levels in a mip-map including the top-level. Note, for levels other than the top-level in the map, dwMipMapCount will specify the number of levels from that map to the smallest map in the chain. New surface capability bit for Direct3D texture loading ------------------------------------------------------- A new surface capability bit, DDSCAPS_ALLOCONLOAD, has been added to support device dependent and compressed texture surfaces. This capability bit specifies that a given texture surface does not have memory allocated for it when it is created. Instead, sufficient memory will be allocated when the texture is loaded using the Direct3D texture Load member. Currently the semantics of this bit are not fully implemented and the width, height and pixel format of the texture surface should be specified when DDSCAPS_ALLOCONLOAD is specified. However, for the final release, width, height and pixel format will not be specified at create time but will be initialized when the texture is loaded. If DDSCAPS_ALLOCONLOAD is specified so must DDSCAPS_TEXTURE. For further information see the Direct3D documentation on the IDirect3DTexture::Load member function. Notes for DirectDraw 2.0 Beta 2 ======================================== Support for high resolutions and TrueColor bit depths ----------------------------------------------------- Direct Draw supports all of the screen resolutions and depths supported by the Display Driver. Version 1.0 of Direct Draw limited the available video modes to 640x480 with pixel depths of 8 bits per pixel and 16 bits per pixel. This restriction has been relaxed and Direct Draw now allows an application to change the mode into any mode supported by the Display Driver. This includes all supported 24 and 32 bits-per-pixel modes. Note that this release of Direct Draw does not check the monitor capabilities stored by the system to determine if a particular display resolution is compatible with the monitor. This means that an application may use EnumerateDisplayModes to determine the available video modes and then switch into a mode that is not supported by the monitor. This is a defect which will be corrected in the next release. HEL Blitting Support for 24 and 32 bit Surfaces ----------------------------------------------- Direct Draw now supports HEL blitting of 24 and 32 bits-per-pixel surfaces. If the Display Driver supports blitting at these resolutions then the hardware blitter will be used for vram to vram blits. Otherwise, the Hardware Emulation Layer (HEL) will be used to do the blits. Multiple Direct Draw Objects per Process ---------------------------------------- Direct Draw 1.0 only allowed the creation of one Direct Draw object per process. If your process happened to use another system component (such as Direct Play) that created a Direct Draw object, the process would be unable to create another Direct Draw object for its own use. This restriction has been eliminated in this release. It is now possible for a process to call DirectDrawCreate as many times as necessary. A unique and independent interface will be returned from each call. Each DirectDraw object may be used as desired. There are no dependencies between the objects. They behave exactly as they would if they had been created by two different processes. Since the Direct Draw objects are independent, surface, palette, and clipper objects which are created with a particular Direct Draw object should not be used with other Direct Draw objects. This is because these objects are automatically released when the Direct Draw object is destroyed. If they are used with another Direct Draw object, they may go away if the original object is destroyed. Clipper objects which are created with DirectDrawClipperCreate are independent of any particular Direct Draw object and may be used with one or more Direct Draw objects. SetCooperativeLevel Doesn't Require an HWND for non-Exclusive Mode ------------------------------------------------------------------ Direct Draw 1.0 required an HWND to be specified in the SetCooperativeLevel call regardless of whether or not Full-screen Exclusive mode was being requested. This function no longer requires an HWND to be specified if the application is requesting DDSCL_NORMAL mode. It is now possible for an application to use Direct Draw with multiple windows. All of these windows may be used simultaneously in normal windowed mode. New IDirectDraw2 and IDirectDrawSurface2 interfaces --------------------------------------------------- The COM model that Direct Draw uses specifies that additional functionality is provided by providing new interfaces. This release of Direct Draw implements a new Direct Draw interface and a new Direct Draw Surface interface. These new interfaces may be obtained by using QueryInterface as shown in the following code fragment: /* * create an IDirectDraw2 interface */ LPDIRECTDRAW lpDD; LPDIRECTDRAW2 lpDD2; ddrval = DirectDrawCreate( NULL, &lpDD, NULL ); if( ddrval != DD_OK ) return; ddrval = lpDD->SetCooperativeLevel( hwnd, DDSCL_NORMAL ); if( ddrval != DD_OK ) return; ddrval = lpDD->QueryInterface( IID_IDirectDraw2, (LPVOID *)&lpDD2); if( ddrval != DD_OK ) return; ddscaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; ddrval = lpDD2->GetAvailableVidMem(&ddscaps, &total, &free); if( ddrval != DD_OK ) return; This code fragment shows C++ syntax for creating an IDirectDraw interface and then using QueryInterface to create an IDirectDraw2 interface. It is this interface which contains the GetAvailableVidMem function. An attempt to use the GetAvailableVidMem function from an IDirectDraw interface will result in a compile-time error. The IDirectDraw2 interface contains all of the same member functions as the IDirectDraw interface along with one additional member functions called GetAvailableVidMem. The SetDisplayMode function in this interface will allow refresh rates to be specified. This is not enabled for this beta and this function will return DDERR_UNSUPPORTED. The SetDisplayMode function in the IDirectDraw interface can be used instead. The IDirectDrawSurface2 interface contains all of the same member functions as the IDirectDrawSurface interface with two additional member functions called PageLock and PageUnlock. The following code fragment shows how to create an IDirectDrawSurface2 interface: LPDIRECTDRAWSURFACE lpSurf; LPDIRECTDRAWSURFACE2 lpSurf2; // Create surfaces memset( &ddsd, 0, sizeof( ddsd ) ); ddsd.dwSize = sizeof( ddsd ); ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; ddsd.dwWidth = 10; ddsd.dwHeight = 10; ddrval = lpDD2->CreateSurface( &ddsd, &lpSurf, NULL ); if( ddrval != DD_OK ) return; ddrval = lpSurf->QueryInterface( IID_IDirectDrawSurface2, (LPVOID *)&lpSurf2); if( ddrval != DD_OK ) return; ddrval = lpSurf2->PageLock( 0 ); if( ddrval != DD_OK ) return; ddrval = lpSurf2->PageUnlock( 0 ); if( ddrval != DD_OK ) return; New PageLock and PageUnlock functions ------------------------------------- A new feature that is supported with this release is the capability for DirectDraw to allow a driver to control the blitting to or from a system memory surface. A driver may choose to do this blitting by copying the bytes one by one or by using DMA transfers. If the driver uses a DMA transfer, it is important that the system memory which contains the bits for the surface is locked so that it cannot be paged out while the DMA is in progress. This can be done using the PageLock and PageUnlock functions available in the IDirectDrawSurface2 interface. HRESULT PageLock( LPDIRECTDRAWSURFACE lpddSurf, DWORD dwFlags ); HRESULT PageUnlock( LPDIRECTDRAWSURFACE lpddSurf, DWORD dwFlags ); There are no flags currently defined for these functions so the only valid value for dwFlags is 0. This function may be called on a vram surface but it will simply return DD_OK without doing anything. If called on a Sytem Memory surface (ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY is nonzero) then all of the memory pages used by this surface will be locked so that they can’t be paged out. A Lock count is maintained for each surface and incremented each time PageLock is called for that surface. The count is decremented when PageUnlock is called. When the count reaches 0, the memory is unlocked and may then be paged by the operating system. Note that the performance of the operating system may be negatively affected if too much memory is locked. The following codes may be returned from these two functions: DD_OK DDERR_INVALIDOBJECT DDERR_INVALIDPARAMS DDERR_SURFACE_LOCK DDERR_CANTPAGELOCK Driver can now Blit to and from System Memory surfaces ------------------------------------------------------ In DirectDraw 1.0, if a surface was in system memory, the HEL automatically performed the blit. Some display cards have DMA hardware which allows them to efficiently blit to and from system memory surfaces. The DDCAPS structure has been expanded to allow drivers to report this capability. The following fields have been added. DWORD dwSVBCaps DWORD dwSVBCKeyCaps DWORD dwSVBFXCaps DWORD dwSVBRops[DD_ROP_SPACE] DWORD dwVSBCaps DWORD dwVSBCKeyCaps DWORD dwVSBFXCaps DWORD dwVSBRops[DD_ROP_SPACE] DWORD dwSSBCaps DWORD dwSSBCKeyCaps DWORD dwSSBFXCaps DWORD dwSSBRops[DD_ROP_SPACE] The SVB prefix indicates capabilities bits that relate to System memory to Video memory Blits. The VSB prefix indicates capabilities bits that relate to Video memory to System memory Blits. The SSB prefix indicates capabilities bits that relate to System memory to System memory Blits. The dwSVBCaps field corresponds to the dwCaps field except that it describes the blitting capabilities of the display driver for System Memory to Video Memory blits. Likewise, the dwSVBCKeyCaps corresponds to the dwCKeyCaps field and dwSVBFXCaps corresponds to dwFXCaps. The dwSVBRops array describes the raster ops that the driver supports for this type of blit. These fields are only valid if the DDCAPS_CANBLTSYSMEM bit is set in dwCaps indicating that the driver is able to blit to or from system memory. If the system memory surface being used by the hardware blitter is not locked, Direct Draw will automatically call PageLock on the surface to insure that the memory has been locked. DirectDraw Palette Objects ========================== Setting Palettes on Non-Primary surfaces ---------------------------------------- In DirectDraw 1.0 palettes could only be attached to the primary surface. Palettes can now be attached to any palletized surface (primary, back buffer, offscreen plain or texture map). Only those palettes attached to primary surfaces will have any effect on the system palette. In it important to note that DirectDraw blits never perform color conversion - any palettes attached to the source or destination surface of a blit are ignored. Furthermore, the DirectDraw surface function GetDC() also ignores any DirectDraw palette selected into the surface. Non-primary surface palettes are intended for use by applications or Direct3D (or other 3D renderer). Sharing Palettes ---------------- Palettes can now be shared between multiple surfaces. The same palette can be set on the front and back buffer of a flipping chain or shared between multiple texture surfaces. When a palette is attached to a surface with SetPalette(), the surface increments the reference count of that palette. When the reference count of the surface reaches zero it will decrement the reference count of the attached palette. In addition, if a palette is detached from a surface by calling SetPalette() with a NULL palette interface pointer, the reference count of the surface's palette will be decremented. Please note that if SetPalette() is called several times consecutively for the same surface with the same palette the reference count for the palette will be incremented once only. Subsequent calls will not effect the palette’s reference count. New Palette Types ----------------- In additional to the 8-bit (256 entry) palettes supported previously, DirectDraw 2.0 supports 1-bit (2 entry), 2-bit (4 entry) and 4-bit (16 entry) palettes. Such palettes can by created by specifying one of the new palette capability flags; DDPCAPS_1BIT, DDPCAPS_2BIT and DDPCAPS_4BIT. Matching capability flags have been added for surface pixel formats (DDPF_PALETTEINDEXED1, DDPF_PALETTEINDEXED2 and DDPF_PALETTEINDEXED4). A palette can only be attached to a surface with a matching pixel format. For example, a 2 entry palette created with the DDPCAPS_1BIT flag can only be attached to a 1-bit surface created with the pixel format flag DDPF_PALETTEINDEXED1 etc. Furthermore, it is now possible to create indexed palettes. An indexed palette is one whose entries do not hold RGB colors but integer indices into the array of PALETTEENTRYs of some target palette. An indexed palette's color table is an array of 2, 4, 16 or 256 bytes where each byte is an index into some unspecified, destination palette. To create an indexed palette specify the palette capability flag DDPCAPS_8BITENTRIES when calling CreatePalette(). For example, to create a 4-bit, indexed palette specify DPCAPS_4BIT | DDPCAPS_8BITENTRIES. When creating an indexed palette a pointer to an array of BYTEs is passed rather than a pointer to an array of PALETTEENTRY structures. The pointer to the array of BYTEs must be cast to an LPPALETTEENTRY when calling CreatePalette(). DirectDraw Clipper Objects ========================== Sharing Clippers ---------------- Clippers can now be shared between multiple surfaces. For example, the same clipper can be set on both the front and back buffers of a flipping chain. When a clipper is attached to a surface with SetClipper(), the surface increments the reference count of that clipper. When the reference count of the surface reaches zero it will decrement the reference count of the attached clipper. In addition, if a clipper is detached from a surface by calling SetClipper() with a NULL clipper interface pointer, the reference count of the surface's clipper will be decremented. Please note that if SetClipper() is called several times consecutively for the same surface with the same clipper the reference count for the clipper will be incremented once only. Subsequent calls will not effect the clipper's reference count. Driver Independent Clippers --------------------------- It is now possible to create clipper objects which are not owned by a DirectDraw driver object. Such clippers can be shared across multiple driver objects. Driver independent clipper objects are created with the new DirectDraw API function DirectDrawCreateClipper(). This function can be called before any DirectDraw driver objects are created. As these clippers are not owned by any DirectDraw driver object, they are not automatically released when an application's driver objects are released. If not released explicitly by the application such clippers will be released by DirectDraw when the application terminates. It is still possible to create clippers with the DirectDraw interface member function CreateClipper(). Such clippers behave identically to the clippers of DirectDraw 1.0. Specifically they will be automatically released when the driver object from which they were created is released. Enhanced Surface Format Support in the Hardware Emulation Layer (HEL) ===================================================================== In DirectDraw 1.0 the Hardware Emulation Layer (HEL) could only create surfaces whose pixel format exactly matched that of the current primary surface. This restriction has been relaxed for DirectDraw 2.0. The HEL now supports the following pixel formats for offscreen plain surfaces. Pixel Format Flags Bit Depth Red Mask Green Mask Blue Mask Alpha Mask DDPF_RGB | DDPF_PALETTEINDEXED1 1 0x00000000 0x00000000 0x00000000 0x00000000 DDPF_RGB | DDPF_PALETTEINDEXED2 2 0x00000000 0x00000000 0x00000000 0x00000000 DDPF_RGB | DDPF_PALETTEINDEXED4 4 0x00000000 0x00000000 0x00000000 0x00000000 DDPF_RGB | DDPF_PALETTEINDEXED8 8 0x00000000 0x00000000 0x00000000 0x00000000 DDPF_RGB 16 0x0000F800 0x000007E0 0x0000001F 0x00000000 DDPF_RGB 16 0x00007C00 0x000003E0 0x0000001F 0x00000000 DDPF_RGB 24 0x00FF0000 0x0000FF00 0x000000FF 0x00000000 DDPF_RGB 24 0x000000FF 0x0000FF00 0x00FF0000 0x00000000 DDPF_RGB 32 0x00FF0000 0x0000FF00 0x000000FF 0x00000000 DDPF_RGB 32 0x000000FF 0x0000FF00 0x00FF0000 0x00000000 In addition to supporting a wider range of offscreen surface formats the HEL also supports surfaces intended for use by Direct3D (or other 3D renders). These surfaces are discussed in the next section. Support for 3D Surfaces ======================= Support for surfaces specific to 3D rendering has been enhanced in DirectDraw 2.0. The 3D specific surface types; texture maps, mipmaps and Z-buffers will be discussed below. Texture Maps ------------ The surface capability flag used to indicate that a surface is a texture is DDSCAPS_TEXTURE. This flag was previously DDSCAPS_TEXTUREMAP but was modified for consistency with Direct3D. Texture maps can now be allocated in system memory using the HEL. To allocate a texture map surface specify the DDSCAPS_TEXTURE flag in the ddsCaps field of the surface description passed to CreateSurface(). A wide range of texture pixel formats are supported by the HEL. These formats are as follows: Pixel Format Flags Bit Depth Red Mask Green Mask Blue Mask Alpha Mask DDPF_RGB | DDPF_PALETTEINDEXED1, 1 0x00000000 0x00000000 0x00000000 0x00000000 DDPF_RGB | DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXEDTO8 1 0x00000000 0x00000000 0x00000000 0x00000000 DDPF_RGB | DDPF_PALETTEINDEXED2 2 0x00000000 0x00000000 0x00000000 0x00000000 DDPF_RGB | DDPF_PALETTEINDEXED2 | DDPF_PALETTEINDEXEDTO8 2 0x00000000 0x00000000 0x00000000 0x00000000 DDPF_RGB | DDPF_PALETTEINDEXED4 4 0x00000000 0x00000000 0x00000000 0x00000000 DDPF_RGB | DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXEDTO8 4 0x00000000 0x00000000 0x00000000 0x00000000 DDPF_RGB | DDPF_PALETTEINDEXED8 8 0x00000000 0x00000000 0x00000000 0x00000000 DDPF_RGB, 8 0x000000E0 0x0000001C 0x00000003 0x00000000 DDPF_RGB | DDPF_ALPHAPIXELS, 16 0x00000F00 0x000000F0 0x0000000F 0x0000F000 DDPF_RGB, 16 0x0000F800 0x000007E0 0x0000001F 0x00000000 DDPF_RGB, 16 0x0000001F 0x000007E0 0x0000F800 0x00000000 DDPF_RGB, 16 0x00007C00 0x000003E0 0x0000001F 0x00000000 DDPF_RGB | DDPF_ALPHAPIXELS, 16 0x00007C00 0x000003E0 0x0000001F 0x00008000 DDPF_RGB, 24 0x00FF0000 0x0000FF00 0x000000FF 0x00000000 DDPF_RGB, 24 0x000000FF 0x0000FF00 0x00FF0000 0x00000000 DDPF_RGB, 32 0x00FF0000 0x0000FF00 0x000000FF 0x00000000 DDPF_RGB, 32 0x000000FF 0x0000FF00 0x00FF0000 0x00000000 DDPF_RGB | DDPF_ALPHAPIXELS, 32 0x00FF0000 0x0000FF00 0x000000FF 0xFF000000 DDPF_RGB | DDPF_ALPHAPIXELS, 32 0x000000FF 0x0000FF00 0x00FF0000 0xFF000000 The above formats are those which can be created by the HEL in system memory. The DirectDraw driver for a 3D accelerated video card is free to create textures of other formats in video memory. Such a driver should export the DDSCAPS_TEXTURE bit to indicate that it can create textures and should be prepared to handle the DirectDraw HAL callback, CanCreateSurface() to verify that the surface description for a texture map is one the driver is prepared to create. Mipmaps ------- DirectDraw 2.0 supports mipmapped texture surfaces. A mipmap is a sequence of textures, each of which is a progressively lower resolution, pre-filtered representation of the same image. Mipmaps are a computationally low cost way of improving the quality of rendered textures. Each pre-filtered image (or level) in the mipmap is a power of two smaller than the previous level. In DirectDraw 2.0 mipmaps are represented as a chain of attached surfaces. The highest resolution texture is at the head of the chain and has, as an attachment, the next level of the mipmap which has, in turn, an attachment which is the next level in the mipmap and so on down to the lowest resolution level of the mipmap. To create a surface representing a single level of a mipmap specify the DDSCAPS_MIPMAP surface capability in the surface description passed to CreateSurface(). As all mipmaps are also textures the DDSCAPS_TEXTURE capability must also be specified. It is possible to create each level manually and build the chain with AddAttachedSurface(). However, CreateSurface() can be used to build an entire mipmap chain in a single operation. The following code fragment demonstrates building a chain of five mipmap levels of sizes 256x256, 128x128, 64x64, 32x32 and 16x16. DDSURFACEDESC ddsd; LPDIRECTDRAWSURFACE lpDDMipMap; ZeroMemory(&ddsd, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_MIPMAPCOUNT; ddsd.dwMipMapCount = 5; ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP | DDSCAPS_COMPLEX; ddsd.dwWidth = 256UL; ddsd.dwHeight = 256UL; ddres = lpDD->CreateSurface(&ddsd, &lpDDMipMap); if (FAILED(ddres)) ... It is permissible to omit the number of mipmaps levels, in which case CreateSurface() will create a chain of surfaces each a power of two smaller than the previous one down to the smallest possible size. It is also possible to omit the width and height in which case CreateSurface() will create the number of levels you specify with a minimum level size of 1x1. A chain of mipmap surfaces is traversed using GetAttachedSurface() specifying the DDSCAPS_MIPMAP and DDSCAPS_TEXTURE capability flags. The following code fragment traverses a mipmap chain from highest to lowest resolutions. LPDIRECTDRAWSURFACE lpDDLevel, lpDDNextLevel; DDSCAPS ddsCaps; lpDDLevel = lpDDMipMap; lpDDLevel->AddRef(); ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP; ddres = DD_OK; while (ddres == DD_OK) { // Process this level ... ddres = lpDDLevel->GetAttachedSurface(&ddsCaps, &lpDDNextLevel); lpDDLevel->Release(); lpDDLevel = lpDDNextLevel; } if ((ddres != DD_OK) && (ddres != DDERR_NOTFOUND)) ... It is also possible to build flippable chains of mipmaps. In this scenario each mipmap level has an associated chain of back buffer texture surfaces. Each back buffer texture is attached to one level of the mipmap. Only the front buffer in the chain has DDSCAPS_MIPMAP set, the others are simply texture maps (DDSCAPS_TEXTURE). A mipmap level can have two attached texture maps, one with the capability flag DDSCAPS_MIPMAP set, which is the next level in the mipmap chain, and one with the capability flag DDSCAPS_BACKBUFFER set, which is back buffer of the flippable chain. Note that all the surfaces in each flippable chain must be of the same size. It is not possible to build such a surface arrangement with a single call to CreateSurface(). To construct a flippable mipmap either build a complex mipmap chain and manually attach backbuffers with AddAttachedSurface() or create a sequence of flippable chains and build the mipmap with AddAttachedSurface(). It is important to note that blit operations apply to only a single level in the mipmap chain. To blit an entire chain of mipmaps each level must be blit separately. Also note that Flip()will not currently flip an entire mipmap chain but only a single level of the mipmap. This is a defect and will be corrected. Z Buffers --------- The DirectDraw HEL can now create Z buffers for use by Direct3D (or other 3D rendering software). The HEL supports both 16 and 32-bit Z buffers. The DirectDraw driver for a 3D accelerated video card can permit the creation of Z buffers in video memory by exporting the surface capability bit DDSCAPS_ZBUFFER. It should also specify the Z buffer depths it supports using the dwZBufferBitDepth field of the DDCAPS structure. Z buffers can be cleared using the DirectDraw surface function Blt(). A new DDBLT_ flag (DDBLT_DEPTHFILL) has been defined to indicate that the blit is a Z buffer clear. If this flag is specified the DDBLTFX structure passed to Blt() should have its dwFillDepth field set to the required Z depth. If the DirectDraw driver for a 3D accelerated video card wishes to provide support for Z buffer clearing in hardware it should export the capability flag DDCAPS_BLTDEPTHFILL and should have code to handle DDBLT_DEPTHFILL blits. The destination surface of a depth fill blit must be a Z buffer. Please note that the actual interpretation of depth value is 3D renderer specific. Direct3D Integration ==================== DirectDraw 2.0 is very tightly integrated with Direct3D. The most important aspects of this integration are discussed below. The Direct3D Driver Interface ----------------------------- DirectDraw 2.0 presents a single, unified driver object to the application programmer. This driver object encapsulates both DirectDraw and Direct3D state. The DirectDraw driver COM interfaces (IID_IDirectDraw or IID_IDirectDraw2) and the Direct3D driver COM interface (IID_IDirect3D) are both interfaces which allow the application programmer to communicate with the same underlying driver object. Hence no Direct3D driver object is created. Rather a Direct3D interface to the DirectDraw driver object is obtained. This is achieved using the standard COM QueryInterface() function. The following code fragment demonstrates creating the DirectDraw driver object and obtaining a Direct3D interface for communicating with that object. LPDIRECTDRAW lpDD; LPDIRECT3D lpD3D; ddres = DirectDrawCreate(NULL, &lpDD, NULL); if (FAILED(ddres)) ... ddres = lpDD->QueryInterface(IID_IDirect3D, &lpD3D); if (FAILED(ddres)) ... The above code creates a single object and obtains two interfaces to that object. Hence, the reference count of the driver object after the QueryInterface() is two. The important implication of this is that the lifetime of the Direct3D driver state is the same as that of the DirectDraw object. Releasing the Direct3D interface does not destroy the Direct3D driver state. That state is not destroyed until all references (both DirectDraw and Direct3D) to that driver object have been released. Hence, if you release a Direct3D interface, while holding a reference to a DirectDraw driver interface, and then re-query the Direct3D interface all the Direct3D state will be preserved. The Direct3D Device Interface ----------------------------- As with the driver object, there is no distinct Direct3D device object. A Direct3D device is simply an interface for communicating with a DirectDraw surface used as a 3D rendering target. For example, the following code fragment creates a Direct3D device interface to a DirectDraw surface object. LPDIRECTDRAWSURFACE lpDDSurface; LPDIRECT3DDEVICE lpD3DDevice; ddres = lpDD->CreateSurface(&ddsd, &lpDDSurface, NULL); if (FAILED(ddres)) ... ddres = lpDDSurface->QueryInterface(lpGuid, &lpD3DDevice); if (FAILED(ddres)) ... The same rules of reference counting and state lifetime discussed for driver objects apply to DirectDraw surfaces and Direct3D devices. Additionally, multiple, distinct Direct3D device interfaces can be obtained for the same DirectDraw surface. Hence, it is possible that a single DirectDraw surface be the target for both a ramp based device and an RGB based device. The Direct3D Texture Interface ------------------------------ Direct3D textures are, once again, not a distinct object type but rather another interface of DirectDraw surface objects. The following code fragment obtains a Direct3D texture interface from a DirectDraw surface object. LPDIRECTDRAWSURFACE lpDDSurface; LPDIRECT3DTEXTURE lpD3DTexture; ddres = lpDD->CreateSurface(&ddsd, &lpDDSurface, NULL); if (FAILED(ddres)) ... ddres = lpDDSurface->QueryInterface(IID_IDirect3DTexture, &lpD3DTexture); if (FAILED(ddres)) ... The same reference counting and state lifetime rules of driver objects and devices apply. It is possible to use a single DirectDraw surface as both a rendering target and a texture. The DirectDraw HEL and Direct3D ------------------------------- The DirectDraw HEL has been enhanced to support the creation of texture, mipmap and Z buffer surfaces. Furthermore, due to the tight integration of DirectDraw and Direct3D, a DirectDraw enabled system will always provide Direct3D support (in software emulation at least). Hence, the DirectDraw HEL exports the DDCAPS_3D capability flag to indicate the availability of Direct3D in software emulation. A DirectDraw driver for a hardware accelerated 3D video card should export this capability flag to indicate the presence of hardware accelerated 3D. GetAvailableVidMem ================== DirectDraw 2.0 adds a new DirectDraw interface function to query the amount of video memory available to a specific type of surface as defined by surface capability flags. To ensure COM compliance this function is not a member of the DirectDraw 1.0 interface but is part of the new DirectDraw 2.0 interface, IID_IDirectDraw2. To invoke this function you must first query for the new DirectDraw interface. The following code fragment demonstrates using GetAvailableVidMem() to determine both the total and free video memory available for texture map surfaces. LPDIRECTDRAW2 lpDD2; DDSCAPS ddsCaps; DWORD dwTotal; DWORD dwFree; ddres = lpDD->QueryInterface(IID_IDirectDraw2, &lpDD2); if (FAILED(ddres)) ... ddsCaps.dwCaps = DDSCAPS_TEXTURE; ddres = lpDD2->GetAvailableVidMem(&ddsCaps, &dwTotal, &dwFree); if (FAILED(ddres)) ... It should be noted that this function gives a snapshot of the current video memory state only. The amount of free video memory is subject to change as surfaces are created and released. Hence, the free memory figure should be used as a rough guide only. In addition, a particular video card may make no distinction between two different memory types. For example, it may use the same portion of video memory to store Z buffers and textures. Hence, allocating one type of surface (a Z buffer say) may affect the amount of video memory available for another type of surface (textures say). Therefore, it is best to first allocate an application's fixed resources (such as front, back and Z buffer) before determining how much memory is available for dynamic use (for texture mapping, for example). Miscellaneous Changes ===================== New Error Return Codes ---------------------- DDERR_NOMIPMAPHW - an attempt was made to create a mipmap in video memory but the hardware DirectDraw driver does not support mipmaps. DDERR_INVALIDSURFACETYPE - an attempt was made to perform an operation on a surface but the capabilities of that surface do not support the operation.